<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>webdoc</title>
    <link rel="stylesheet" type="text/css" href="../static/css/main.css">
</head>
<body>
<div class="nav">
    <div class="logo">
        
            webdoc
        
    </div>
<ul><li><a href="../index.html">0.Async</a></li><li><a href="../html/0.editor.html">0.editor</a></li><li><a href="../html/0.module.html">0.module</a></li><li><a href="../html/1.ES2015.html">1.ES2015</a></li><li><a href="../html/2.Promise.html">2.Promise</a></li><li><a href="../html/3.Node.html">3.Node</a></li><li><a href="../html/4.NodeInstall.html">4.NodeInstall</a></li><li><a href="../html/5.REPL.html">5.REPL</a></li><li><a href="../html/6.NodeCore.html">6.NodeCore</a></li><li><a href="../html/7.module&NPM.html">7.module&NPM</a></li><li><a href="../html/8.Encoding.html">8.Encoding</a></li><li><a href="../html/9.Buffer.html">9.Buffer</a></li><li><a href="../html/10.fs.html">10.fs</a></li><li><a href="../html/11.Stream-1.html">11.Stream-1</a></li><li><a href="../html/11.Stream-2.html">11.Stream-2</a></li><li><a href="../html/11.Stream-3.html">11.Stream-3</a></li><li><a href="../html/11.Stream-4.html">11.Stream-4</a></li><li><a href="../html/12-Network-2.html">12-Network-2</a></li><li><a href="../html/12.NetWork-3.html">12.NetWork-3</a></li><li><a href="../html/12.Network-1.html">12.Network-1</a></li><li><a href="../html/13.tcp.html">13.tcp</a></li><li><a href="../html/14.http-1.html">14.http-1</a></li><li><a href="../html/14.http-2.html">14.http-2</a></li><li><a href="../html/15.compress.html">15.compress</a></li><li><a href="../html/16.crypto.html">16.crypto</a></li><li><a href="../html/17.process.html">17.process</a></li><li><a href="../html/18.yargs.html">18.yargs</a></li><li><a href="../html/19.cache.html">19.cache</a></li><li><a href="../html/20.action.html">20.action</a></li><li><a href="../html/21.https.html">21.https</a></li><li><a href="../html/22.cookie.html">22.cookie</a></li><li><a href="../html/23.session.html">23.session</a></li><li><a href="../html/24.express-1.html">24.express-1</a></li><li><a href="../html/24.express-2.html">24.express-2</a></li><li><a href="../html/24.express-3.html">24.express-3</a></li><li><a href="../html/24.express-4.html">24.express-4</a></li><li><a href="../html/25.koa-1.html">25.koa-1</a></li><li><a href="../html/26.webpack-1-basic.html">26.webpack-1-basic</a></li><li><a href="../html/26.webpack-2-optimize.html">26.webpack-2-optimize</a></li><li><a href="../html/26.webpack-3.tapable.html">26.webpack-3.tapable</a></li><li><a href="../html/26.webpack-4-AST.html">26.webpack-4-AST</a></li><li><a href="../html/26.webpack-5-source.html">26.webpack-5-source</a></li><li><a href="../html/26.webpack-6-loader.html">26.webpack-6-loader</a></li><li><a href="../html/26.webpack-7-plugin.html">26.webpack-7-plugin</a></li><li><a href="../html/26.webpack-8-hand.html">26.webpack-8-hand</a></li><li><a href="../html/27.react-1.html">27.react-1</a></li><li><a href="../html/27.react-2.html">27.react-2</a></li><li><a href="../html/27.react-3.html">27.react-3</a></li><li><a href="../html/27.react-4-immutable.html">27.react-4-immutable</a></li><li><a href="../html/27.react-5-react-dom-diff.html">27.react-5-react-dom-diff</a></li><li><a href="../html/27.react-6.html">27.react-6</a></li><li><a href="../html/28.react-mobx.html">28.react-mobx</a></li><li><a href="../html/28.redux-0.html">28.redux-0</a></li><li><a href="../html/28.redux-1.html">28.redux-1</a></li><li><a href="../html/28.redux-2-中间件.html">28.redux-2-中间件</a></li><li><a href="../html/28.redux-3-saga.html">28.redux-3-saga</a></li><li><a href="../html/28.redux-jwt-back.html">28.redux-jwt-back</a></li><li><a href="../html/28.redux-jwt-front.html">28.redux-jwt-front</a></li><li><a href="../html/29.mongodb-1.html">29.mongodb-1</a></li><li><a href="../html/29.mongodb-2.html">29.mongodb-2</a></li><li><a href="../html/29.mongodb-3.html">29.mongodb-3</a></li><li><a href="../html/29.mongodb-4.html">29.mongodb-4</a></li><li><a href="../html/29.mongodb-5.html">29.mongodb-5</a></li><li><a href="../html/29.mongodb-6.html">29.mongodb-6</a></li><li><a href="../html/30.cms-1-mysql.html">30.cms-1-mysql</a></li><li><a href="../html/30.cms-2-mysql.html">30.cms-2-mysql</a></li><li><a href="../html/30.cms-3-mysql.html">30.cms-3-mysql</a></li><li><a href="../html/30.cms-4-egg.html">30.cms-4-egg</a></li><li><a href="../html/30.cms-5-api.html">30.cms-5-api</a></li><li><a href="../html/30.cms-6-roadhog.html">30.cms-6-roadhog</a></li><li><a href="../html/30.cms-7-umi.html">30.cms-7-umi</a></li><li><a href="../html/30.cms-8-dva.html">30.cms-8-dva</a></li><li><a href="../html/30.cms-9-dva.html">30.cms-9-dva</a></li><li><a href="../html/30.cms-10-dva.html">30.cms-10-dva</a></li><li><a href="../html/30.cms-11-front.html">30.cms-11-front</a></li><li><a href="../html/31.cms-12-api.html">31.cms-12-api</a></li><li><a href="../html/31.cms-13-front.html">31.cms-13-front</a></li><li><a href="../html/31.cms-14-deploy.html">31.cms-14-deploy</a></li><li><a href="../html/32.ant.html">32.ant</a></li><li><a href="../html/33.redis.html">33.redis</a></li><li><a href="../html/34.unittest.html">34.unittest</a></li><li><a href="../html/35.jwt.html">35.jwt</a></li><li><a href="../html/36.websocket-1.html">36.websocket-1</a></li><li><a href="../html/36.websocket-2.html">36.websocket-2</a></li><li><a href="../html/38.chat-api-1.html">38.chat-api-1</a></li><li><a href="../html/38.chat-api-2.html">38.chat-api-2</a></li><li><a href="../html/38.chat-3.html">38.chat-3</a></li><li><a href="../html/38.chat-api-3.html">38.chat-api-3</a></li><li><a href="../html/38.chat.html">38.chat</a></li><li class="active"><a href="../html/38.chat2.html">38.chat2</a></li><li class="active"><a href="../html/38.chat2.html">38.chat2</a></li><li><a href="../html/39.crawl-0.html">39.crawl-0</a></li><li><a href="../html/39.crawl-1.html">39.crawl-1</a></li><li><a href="../html/39.crawl-2.html">39.crawl-2</a></li><li><a href="../html/40.deploy.html">40.deploy</a></li><li><a href="../html/41.safe.html">41.safe</a></li><li><a href="../html/42.test.html">42.test</a></li><li><a href="../html/43.nginx.html">43.nginx</a></li><li><a href="../html/44.enzyme.html">44.enzyme</a></li><li><a href="../html/45.docker.html">45.docker</a></li><li><a href="../html/46.elastic.html">46.elastic</a></li><li><a href="../html/47.oauth.html">47.oauth</a></li><li><a href="../html/48.wxpay.html">48.wxpay</a></li><li><a href="../html/49.nunjucks.html">49.nunjucks</a></li><li><a href="../html/50.ketang.html">50.ketang</a></li><li><a href="../html/index.html">index</a></li><li><a href="../html/51.typescript.html">51.typescript</a></li><li><a href="../html/52.UML.html">52.UML</a></li><li><a href="../html/53.design.html">53.design</a></li><li><a href="../html/index.html">index</a></li></ul></div>


<div class="warpper">

    <div class="page-toc">
        <ul><li><a href="#t01. 生成项目">1. 生成项目</a></li><li><a href="#t12. 实现注册和登录">2. 实现注册和登录</a><ul><li><a href="#t22.1 User/_layout.js">2.1 User/_layout.js</a></li><li><a href="#t32.2 User/User.less">2.2 User/User.less</a></li><li><a href="#t42.3 User/Register.js">2.3 User/Register.js</a></li><li><a href="#t52.4  User/Register.less">2.4  User/Register.less</a></li></ul></li><li><a href="#t63. 实现手机验证码验证">3. 实现手机验证码验证</a><ul><li><a href="#t73.1 request.js">3.1 request.js</a></li><li><a href="#t83.2 User/Register.js">3.2 User/Register.js</a></li><li><a href="#t93.3 models/register.js">3.3 models/register.js</a></li><li><a href="#t103.4 services/register.js">3.4 services/register.js</a></li><li><a href="#t113.5 server/app.js">3.5 server/app.js</a></li><li><a href="#t123.6 routes/user.js">3.6 routes/user.js</a></li><li><a href="#t133.7 server/config.js">3.7 server/config.js</a></li></ul></li><li><a href="#t144.手机注册和登录">4.手机注册和登录</a><ul><li><a href="#t154.1 server/app.js">4.1 server/app.js</a></li><li><a href="#t164.2 server/config.js">4.2 server/config.js</a></li><li><a href="#t174.3 models/index.js">4.3 models/index.js</a></li><li><a href="#t184.4 routes/user.js">4.4 routes/user.js</a></li><li><a href="#t194.5 Rooms/index.jsx">4.5 Rooms/index.jsx</a></li><li><a href="#t204.6 User/Login.jsx">4.6 User/Login.jsx</a></li><li><a href="#t214.7 User/Login.less">4.7 User/Login.less</a></li><li><a href="#t224.8 User/Register.jsx">4.8 User/Register.jsx</a></li><li><a href="#t234.9 models/login.js">4.9 models/login.js</a></li><li><a href="#t244.10 models/register.js">4.10 models/register.js</a></li><li><a href="#t254.11 services/login.js">4.11 services/login.js</a></li><li><a href="#t264.12 services/register.js">4.12 services/register.js</a></li><li><a href="#t274.13 utils/request.js">4.13 utils/request.js</a></li></ul></li><li><a href="#t285. 实现房间功能">5. 实现房间功能</a><ul><li><a href="#t295.1 server/app.js">5.1 server/app.js</a></li><li><a href="#t305.2 models/index.js">5.2 models/index.js</a></li><li><a href="#t315.3 routes/room.js">5.3 routes/room.js</a></li><li><a href="#t325.4 Room/index.jsx">5.4 Room/index.jsx</a></li><li><a href="#t335.5 Room/index.less">5.5 Room/index.less</a></li><li><a href="#t345.6 models/room.js">5.6 models/room.js</a></li><li><a href="#t355.7 services/room.js">5.7 services/room.js</a></li></ul></li><li><a href="#t366. 实现聊天功能">6. 实现聊天功能</a><ul><li><a href="#t376.1 server/app.js">6.1 server/app.js</a></li><li><a href="#t386.2 models/index.js">6.2 models/index.js</a></li><li><a href="#t396.3 routes/user.js">6.3 routes/user.js</a></li><li><a href="#t406.4 Room/$id.jsx">6.4 Room/$id.jsx</a></li><li><a href="#t416.5 Room/index.jsx">6.5 Room/index.jsx</a></li><li><a href="#t426.6 models/chat.js">6.6 models/chat.js</a></li><li><a href="#t436.7 models/room.js">6.7 models/room.js</a></li><li><a href="#t446.8 models/login.js">6.8 models/login.js</a></li></ul></li><li><a href="#t457. 上传图片">7. 上传图片</a><ul><li><a href="#t467.1 server/app.js">7.1 server/app.js</a></li><li><a href="#t477.2 models/index.js">7.2 models/index.js</a></li><li><a href="#t487.3 routes/room.js">7.3 routes/room.js</a></li><li><a href="#t497.4 routes/user.js">7.4 routes/user.js</a></li><li><a href="#t507.5 Room/index.jsx">7.5 Room/index.jsx</a></li><li><a href="#t517.6 /models/chat.js">7.6 /models/chat.js</a></li><li><a href="#t527.7 models/room.js">7.7 models/room.js</a></li><li><a href="#t537.8 models/login.js">7.8 models/login.js</a></li><li><a href="#t547.9 services/login.js">7.9 services/login.js</a></li></ul></li><li><a href="#t55参考链接">参考链接</a></li></ul>
    </div>
    
    <div class="content markdown-body">
        <h2 id="t01. &#x751F;&#x6210;&#x9879;&#x76EE;">1. &#x751F;&#x6210;&#x9879;&#x76EE; <a href="#t01. &#x751F;&#x6210;&#x9879;&#x76EE;"> # </a></h2>
<pre><code class="lang-js">$ npm install dva-cli -g
$ dva -v
$ dva <span class="hljs-keyword">new</span> zhufeng-dva-chat
</code></pre>
<h2 id="t12. &#x5B9E;&#x73B0;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55;">2. &#x5B9E;&#x73B0;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55; <a href="#t12. &#x5B9E;&#x73B0;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55;"> # </a></h2>
<h3 id="t22.1 User/_layout.js">2.1 User/_layout.js <a href="#t22.1 User/_layout.js"> # </a></h3>
<p>src/pages/User/_layout.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./User.less&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserLayout</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    render() {
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
                {this.props.children}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        )
    }
}
</code></pre>
<h3 id="t32.2 User/User.less">2.2 User/User.less <a href="#t32.2 User/User.less"> # </a></h3>
<p>src/pages/User/User.less</p>
<pre><code class="lang-less"><span class="hljs-selector-class">.container</span>{
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">height</span>:<span class="hljs-number">100%</span>;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
}
</code></pre>
<h3 id="t42.3 User/Register.js">2.3 User/Register.js <a href="#t42.3 User/Register.js"> # </a></h3>
<p>src/pages/User/Register.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/link&apos;</span>;
<span class="hljs-keyword">import</span> { Form, Input, Button, Select, Row, Col, Popover, Progress } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./Register.less&apos;</span>;
<span class="hljs-keyword">const</span> FormItem = Form.Item;
<span class="hljs-keyword">const</span> { Option } = Select;
<span class="hljs-keyword">const</span> InputGroup=Input.Group;

<span class="hljs-keyword">const</span> passwordStatusMap = {
    <span class="hljs-attr">ok</span>: (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.success}</span>&gt;</span>
        &#x5F3A;&#x5EA6;: &#x5F3A;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    ),
    <span class="hljs-attr">pass</span>: (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.warning}</span>&gt;</span>
        v&#x5F3A;&#x5EA6;: &#x4E2D;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    ),
    <span class="hljs-attr">poor</span>: (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.error}</span>&gt;</span>
        &#x5F3A;&#x5EA6;: &#x592A;&#x77ED;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    ),
};
<span class="hljs-keyword">const</span> passwordProgressMap = {
    <span class="hljs-attr">ok</span>: <span class="hljs-string">&apos;success&apos;</span>,
    <span class="hljs-attr">pass</span>: <span class="hljs-string">&apos;normal&apos;</span>,
    <span class="hljs-attr">poor</span>: <span class="hljs-string">&apos;exception&apos;</span>,
  };


@connect(<span class="hljs-function">(<span class="hljs-params">{ register, loading }</span>) =&gt;</span> ({
    register,
    <span class="hljs-attr">submitting</span>: loading.effects[<span class="hljs-string">&apos;register/submit&apos;</span>],
  }))
@Form.create()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    state = {
        <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">confirmDirty</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">visible</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">help</span>: <span class="hljs-string">&apos;&apos;</span>,
        <span class="hljs-attr">prefix</span>: <span class="hljs-string">&apos;86&apos;</span>,
    };
    getPasswordStatus=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> { form } = <span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> value = form.getFieldValue(<span class="hljs-string">&apos;password&apos;</span>);
        <span class="hljs-keyword">if</span> (value &amp;&amp; value.length &gt; <span class="hljs-number">9</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;ok&apos;</span>;
        }
        <span class="hljs-keyword">if</span> (value &amp;&amp; value.length &gt; <span class="hljs-number">5</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;pass&apos;</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;poor&apos;</span>;
    };

    renderPasswordProgress = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> { form } = <span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> value = form.getFieldValue(<span class="hljs-string">&apos;password&apos;</span>);
        <span class="hljs-keyword">const</span> passwordStatus = <span class="hljs-keyword">this</span>.getPasswordStatus();
        <span class="hljs-keyword">return</span> value &amp;&amp; value.length ? (
          &lt;div className={styles[`progress-${passwordStatus}`]}&gt;
            &lt;Progress
              status={passwordProgressMap[passwordStatus]}
              className={styles.progress}
              strokeWidth={6}
              percent={value.length * 10 &gt; 100 ? 100 : value.length * 10}
              showInfo={false}
            /&gt;
          &lt;/div&gt;
        ) : null;
      };

      checkPassword = (rule, value, callback) =&gt; {
        const { visible, confirmDirty } = this.state;
        if (!value) {
          this.setState({
            help:&quot;&#x8BF7;&#x8F93;&#x5165;&#x5BC6;&#x7801;!&quot;,
            visible: !!value,
          });
          callback(&apos;error&apos;);
        } else {
          this.setState({
            help: &apos;&apos;,
          });
          if (!visible) {
            this.setState({
              visible: !!value,
            });
          }
          if (value.length &lt; 6) {
            callback(&apos;error&apos;);
          } else {
            const { form } = this.props;
            if (value &amp;&amp; confirmDirty) {
              form.validateFields([&apos;confirm&apos;], { force: true });
            }
            callback();
          }
        }
      };
    checkConfirm = (rule, value, callback) =&gt; {
        const { form } = this.props;
        if (value &amp;&amp; value !== form.getFieldValue(&apos;password&apos;)) {
          callback(&apos;&#x4E24;&#x6B21;&#x8F93;&#x5165;&#x7684;&#x5BC6;&#x7801;&#x4E0D;&#x5339;&#x914D;!&apos;);
        } else {
          callback();
        }
    };
    changePrefix = value =&gt; {
        this.setState({
          prefix: value,
        });
    };
    onGetCaptcha = () =&gt; {
        let count = 59;
        this.setState({ count });
        this.interval = setInterval(() =&gt; {
          count -= 1;
          this.setState({ count });
          if (count === 0) {
            clearInterval(this.interval);
          }
        }, 1000);
      };
    render() {
        const { form, submitting } = this.props;
        const {getFieldDecorator}=form;
        const { count, prefix, help, visible } = this.state;
        return (
            &lt;div className={styles.register}&gt;
                &lt;h3&gt;&#x7528;&#x6237;&#x6CE8;&#x518C;&lt;/h3&gt;
                &lt;Form onSubmit={this.handleSubmit}&gt;
                    &lt;FormItem&gt;
                        {getFieldDecorator(&apos;mail&apos;, {
                            rules: [
                                {
                                required: true,
                                message:  &apos;&#x90AE;&#x7BB1;&#x5FC5;&#x987B;&#x8F93;&#x5165;&apos;,
                                },
                                {
                                type: &apos;email&apos;,
                                message: &apos;&#x90AE;&#x7BB1;&#x683C;&#x5F0F;&#x4E0D;&#x5408;&#x6CD5;&apos;,
                                },
                            ],
                        })(
                        &lt;Input size=&quot;large&quot; placeholder=&quot;&#x90AE;&#x7BB1;&quot;/&gt;
                        )}
                    &lt;/FormItem&gt;
                    &lt;FormItem help={help}&gt;
                        &lt;Popover
                        content={
                            &lt;div style={{ padding: &apos;4px 0&apos; }}&gt;
                                {passwordStatusMap[this.getPasswordStatus()]}
                                {this.renderPasswordProgress()}
                                &lt;div style={{ marginTop: 10 }}&gt;
                                  &#x8BF7;&#x81F3;&#x5C11;&#x8F93;&#x5165; 6 &#x4E2A;&#x5B57;&#x7B26;&#x3002;&#x8BF7;&#x4E0D;&#x8981;&#x4F7F;&#x7528;&#x5BB9;&#x6613;&#x88AB;&#x731C;&#x5230;&#x7684;&#x5BC6;&#x7801;&#x3002;
                                &lt;/div&gt;
                            &lt;/div&gt;
                        }
                        overlayStyle={{ width: 240 }}
                        placement=&quot;right&quot;
                        visible={visible}
                        &gt;
                        {getFieldDecorator(&apos;password&apos;, {
                            rules: [
                            {
                                validator: this.checkPassword,
                            },
                            ],
                        })(
                            &lt;Input
                              size=&quot;large&quot;
                              type=&quot;password&quot;
                              placeholder=&apos;&#x81F3;&#x5C11;&#x516D;&#x4F4D;&#x5BC6;&#x7801;&#xFF0C;&#x533A;&#x5206;&#x5927;&#x5C0F;&#x5199;&apos;
                            /&gt;
                        )}
                        &lt;/Popover&gt;
                    &lt;/FormItem&gt;
                &lt;FormItem&gt;
                    {getFieldDecorator(&apos;confirm&apos;, {
                    rules: [
                        {
                         required: true,
                         message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x786E;&#x8BA4;&#x5BC6;&#x7801;&#xFF01;&apos;,
                        },
                        {
                         validator: this.checkConfirm,
                        },
                    ],
                    })(
                    &lt;Input
                        size=&quot;large&quot;
                        type=&quot;password&quot;
                        placeholder=&quot;&#x786E;&#x8BA4;&#x5BC6;&#x7801;&quot;
                    /&gt;
                    )}
                &lt;/FormItem&gt;
                &lt;FormItem&gt;
                    &lt;InputGroup compact&gt;
                    &lt;Select
                        size=&quot;large&quot;
                        value={prefix}
                        onChange={this.changePrefix}
                        style={{ width: &apos;20%&apos; }}
                    &gt;
                        &lt;Option value=&quot;86&quot;&gt;+86&lt;/Option&gt;
                        &lt;Option value=&quot;87&quot;&gt;+87&lt;/Option&gt;
                    &lt;/Select&gt;
                    {getFieldDecorator(&apos;mobile&apos;, {
                        rules: [
                        {
                            required: true,
                            message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x624B;&#x673A;&#x53F7;!&apos;,
                        },
                        {
                            pattern: /^\d{11}$/,
                            message: &apos;&#x624B;&#x673A;&#x53F7;&#x683C;&#x5F0F;&#x9519;&#x8BEF;&#xFF01;&apos;,
                        },
                        ],
                    })(
                        &lt;Input
                        size=&quot;large&quot;
                        style={{ width: &apos;80%&apos; }}
                        placeholder=&apos;&#x624B;&#x673A;&#x53F7;&apos;
                        /&gt;
                    )}
                    &lt;/InputGroup&gt;
                &lt;/FormItem&gt;
                &lt;FormItem&gt;
                    &lt;Row gutter={8}&gt;
                        &lt;Col span={16}&gt;
                            {getFieldDecorator(&apos;captcha&apos;, {
                            rules: [
                                {
                                required: true,
                                message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x9A8C;&#x8BC1;&#x7801;&#xFF01;&apos;,
                                },
                            ],
                            })(
                            &lt;Input
                                size=&quot;large&quot;
                                placeholder=&quot;&#x9A8C;&#x8BC1;&#x7801;&quot;
                            /&gt;
                            )}
                        &lt;/Col&gt;
                        &lt;Col span={8}&gt;
                            &lt;Button
                            size=&quot;large&quot;
                            disabled={count}
                            className={styles.getCaptcha}
                            onClick={this.onGetCaptcha}
                            &gt;
                              {count? `${count} s`: &apos;&#x83B7;&#x53D6;&#x9A8C;&#x8BC1;&#x7801;&apos;}
                            &lt;/Button&gt;
                        &lt;/Col&gt;
                    &lt;/Row&gt;
                &lt;/FormItem&gt;
                &lt;FormItem&gt;
                    &lt;Button
                    size=&quot;large&quot;
                    loading={submitting}
                    className={styles.submit}
                    type=&quot;primary&quot;
                    htmlType=&quot;submit&quot;
                    &gt;
                    &#x6CE8;&#x518C;
                    &lt;/Button&gt;
                    &lt;Link className={styles.login} to=&quot;/User/Login&quot;&gt;
                      &#x4F7F;&#x7528;&#x5DF2;&#x6709;&#x8D26;&#x6237;&#x767B;&#x5F55;
                    &lt;/Link&gt;
                &lt;/FormItem&gt;
              &lt;/Form&gt;
            &lt;/div&gt;

        );
    }
}
</code></pre>
<h3 id="t52.4  User/Register.less">2.4  User/Register.less <a href="#t52.4  User/Register.less"> # </a></h3>
<p>src/pages/User/Register.less</p>
<pre><code class="lang-less"><span class="hljs-selector-class">.register</span>{
    <span class="hljs-attribute">width</span>:<span class="hljs-number">450px</span>;
    <span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid <span class="hljs-number">#CCC</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding</span>:<span class="hljs-number">20px</span>;
    <span class="hljs-selector-tag">h3</span>{
        <span class="hljs-attribute">text-align</span>: center;
    }
    <span class="hljs-selector-class">.getCaptcha</span>{
        <span class="hljs-attribute">width</span>:<span class="hljs-number">100%</span>;
        <span class="hljs-attribute">display</span>:block;
    }
    <span class="hljs-selector-class">.login</span>{
        <span class="hljs-attribute">float</span>:right;
    }
}
</code></pre>
<h2 id="t63. &#x5B9E;&#x73B0;&#x624B;&#x673A;&#x9A8C;&#x8BC1;&#x7801;&#x9A8C;&#x8BC1;">3. &#x5B9E;&#x73B0;&#x624B;&#x673A;&#x9A8C;&#x8BC1;&#x7801;&#x9A8C;&#x8BC1; <a href="#t63. &#x5B9E;&#x73B0;&#x624B;&#x673A;&#x9A8C;&#x8BC1;&#x7801;&#x9A8C;&#x8BC1;"> # </a></h2>
<h3 id="t73.1 request.js">3.1 request.js <a href="#t73.1 request.js"> # </a></h3>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> fetch <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva/fetch&apos;</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseJSON</span>(<span class="hljs-params">response</span>) </span>{
  <span class="hljs-keyword">return</span> response.json();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkStatus</span>(<span class="hljs-params">response</span>) </span>{
  <span class="hljs-keyword">if</span> (response.status &gt;= <span class="hljs-number">200</span> &amp;&amp; response.status &lt; <span class="hljs-number">300</span>) {
    <span class="hljs-keyword">return</span> response;
  }

  <span class="hljs-keyword">const</span> error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(response.statusText);
  error.response = response;
  <span class="hljs-keyword">throw</span> error;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkSuccess</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">if</span> (data.code == <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> data;
  }

  <span class="hljs-keyword">const</span> error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(data.error);
  <span class="hljs-keyword">throw</span> error;
}

<span class="hljs-comment">/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to &quot;fetch&quot;
 * @return {object}           An object containing either &quot;data&quot; or &quot;err&quot;
 */</span>
<span class="hljs-keyword">const</span> HOST=<span class="hljs-string">&apos;http://localhost:3000&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">request</span>(<span class="hljs-params">url, options</span>) </span>{
  <span class="hljs-keyword">return</span> fetch(HOST+url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(checkSuccess)
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> ({ err }));
}
</code></pre>
<h3 id="t83.2 User/Register.js">3.2 User/Register.js <a href="#t83.2 User/Register.js"> # </a></h3>
<p>src/pages/User/Register.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-    onGetCaptcha = () =&gt; {</span>
<span class="hljs-addition">+    onGetCaptcha=() =&gt; {</span>
<span class="hljs-addition">+        const {dispatch,form}=this.props;</span>
<span class="hljs-addition">+        let mobile=form.getFieldValue(&apos;mobile&apos;);</span>
<span class="hljs-addition">+        dispatch({</span>
<span class="hljs-addition">+            type: &apos;register/getCaptcha&apos;,</span>
<span class="hljs-addition">+            payload:mobile</span>
<span class="hljs-addition">+        });</span>
</code></pre>
<h3 id="t93.3 models/register.js">3.3 models/register.js <a href="#t93.3 models/register.js"> # </a></h3>
<p>src/pages/User/models/register.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> registerService <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../services/register&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">namespace</span>: <span class="hljs-string">&apos;register&apos;</span>,
  <span class="hljs-attr">state</span>: {

  },
  <span class="hljs-attr">effects</span>: {
      *getCaptcha({payload},{call,put}) {
        <span class="hljs-keyword">const</span> {data} = <span class="hljs-keyword">yield</span> call(registerService.getCaptcha,payload);
        <span class="hljs-built_in">console</span>.log(data);
    }
  },
  <span class="hljs-attr">reducers</span>: {}
};
</code></pre>
<h3 id="t103.4 services/register.js">3.4 services/register.js <a href="#t103.4 services/register.js"> # </a></h3>
<p>src/pages/User/services/register.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../../../utils/request&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCaptcha</span>(<span class="hljs-params">mobile</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/user/getCaptcha?mobile=<span class="hljs-subst">${mobile}</span>`</span>);
}
</code></pre>
<h3 id="t113.5 server/app.js">3.5 server/app.js <a href="#t113.5 server/app.js"> # </a></h3>
<p>server/app.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> express=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express&apos;</span>);
<span class="hljs-keyword">let</span> session=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express-session&apos;</span>);
<span class="hljs-keyword">const</span> cors=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;cors&apos;</span>);
<span class="hljs-keyword">let</span> app=express();
app.use(cors());
app.use(session({
    <span class="hljs-attr">resave</span>:<span class="hljs-literal">true</span>,
    <span class="hljs-attr">secret</span>:<span class="hljs-string">&apos;zfpx&apos;</span>,
    <span class="hljs-attr">saveUninitialized</span>:<span class="hljs-literal">true</span>
}));
<span class="hljs-keyword">let</span> user=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;./routes/user&apos;</span>);
app.use(<span class="hljs-string">&apos;/user&apos;</span>,user);
app.listen(<span class="hljs-number">3000</span>);
</code></pre>
<h3 id="t123.6 routes/user.js">3.6 routes/user.js <a href="#t123.6 routes/user.js"> # </a></h3>
<p>server/routes/user.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> express=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express&apos;</span>);
<span class="hljs-keyword">let</span> router=express.Router();
<span class="hljs-keyword">let</span> axios=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;axios&apos;</span>);
<span class="hljs-keyword">let</span> {SMS}=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../config&apos;</span>);
router.get(<span class="hljs-string">&apos;/getCaptcha&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> {mobile}=req.query;
    <span class="hljs-keyword">let</span> captcha=<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getMilliseconds();
    req.session.captcha = captcha;
    <span class="hljs-keyword">let</span> {data} = <span class="hljs-keyword">await</span> axios({
        <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
        <span class="hljs-attr">url</span>: <span class="hljs-string">&apos;https://open.ucpaas.com/ol/sms/sendsms&apos;</span>,
        <span class="hljs-attr">data</span>: {
            ...SMS,
            mobile,
            <span class="hljs-attr">param</span>:captcha,
        },
        <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">&quot;Content-Type&quot;</span>: <span class="hljs-string">&quot;application/json;charset=utf-8&quot;</span>,
            <span class="hljs-string">&quot;Accept&quot;</span>: <span class="hljs-string">&quot;application/json&quot;</span>
        }
    });
    <span class="hljs-keyword">if</span> (data.code == <span class="hljs-string">&apos;000000&apos;</span>) {
        res.json({<span class="hljs-attr">code</span>: <span class="hljs-number">0</span>,<span class="hljs-attr">data</span>:captcha});
    } <span class="hljs-keyword">else</span> {
        res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">1</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;&#x83B7;&#x53D6;&#x9A8C;&#x8BC1;&#x7801;&#x5931;&#x8D25;!&apos;</span>});
    }
});
<span class="hljs-built_in">module</span>.exports=router;
</code></pre>
<h3 id="t133.7 server/config.js">3.7 server/config.js <a href="#t133.7 server/config.js"> # </a></h3>
<p>server/config.js</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports={
    <span class="hljs-attr">SMS</span>: {
        <span class="hljs-attr">sid</span>: <span class="hljs-string">&apos;32548fb951ac0df279db0e6e9a515566@&apos;</span>,   <span class="hljs-comment">//&#x5F00;&#x53D1;&#x8005;&#x8D26;&#x53F7;id &#x53BB;&#x6389;@</span>
    token: <span class="hljs-string">&apos;aa0309c08920ca38201de69eb3c745b6@&apos;</span>, <span class="hljs-comment">//&#x5F00;&#x53D1;&#x8005;token</span>
    appid: <span class="hljs-string">&apos;16129d504b7c484c9e8f09b4ec929983@&apos;</span>, <span class="hljs-comment">//&#x5E94;&#x7528;id</span>
        templateid: <span class="hljs-string">&apos;387675&apos;</span>,                      <span class="hljs-comment">//&#x77ED;&#x4FE1;&#x6A21;&#x677F;id</span>
    }
}
</code></pre>
<h2 id="t144.&#x624B;&#x673A;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55;">4.&#x624B;&#x673A;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55; <a href="#t144.&#x624B;&#x673A;&#x6CE8;&#x518C;&#x548C;&#x767B;&#x5F55;"> # </a></h2>
<h3 id="t154.1 server/app.js">4.1 server/app.js <a href="#t154.1 server/app.js"> # </a></h3>
<p>server/app.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+const bodyParser=require(&apos;body-parser&apos;);</span>
 let app=express();
<span class="hljs-deletion">-app.use(cors());</span>
<span class="hljs-addition">+app.use(cors({</span>
<span class="hljs-addition">+    origin:&apos;http://localhost:8000&apos;,</span>
<span class="hljs-addition">+    credentials:true</span>
<span class="hljs-addition">+}));</span>
<span class="hljs-addition">+app.use(bodyParser.json());</span>
</code></pre>
<h3 id="t164.2 server/config.js">4.2 server/config.js <a href="#t164.2 server/config.js"> # </a></h3>
<p>server/config.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+    DB: {</span>
<span class="hljs-addition">+        url:&apos;mongodb://localhost/chat&apos;</span>
<span class="hljs-addition">+    }</span>
</code></pre>
<h3 id="t174.3 models/index.js">4.3 models/index.js <a href="#t174.3 models/index.js"> # </a></h3>
<p>server/models/index.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;mongoose&apos;</span>);
<span class="hljs-keyword">const</span> Schema = mongoose.Schema;
<span class="hljs-keyword">const</span> ObjectId = Schema.Types.ObjectId;
<span class="hljs-keyword">const</span> {
  DB
} = <span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../config&apos;</span>);
<span class="hljs-keyword">const</span> conn = mongoose.createConnection(DB.url,{ <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
<span class="hljs-keyword">const</span> User = conn.model(<span class="hljs-string">&apos;User&apos;</span>, {
    <span class="hljs-attr">email</span>: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},
    <span class="hljs-attr">password</span>: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},
    <span class="hljs-attr">mobile</span>:{<span class="hljs-attr">type</span>:<span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>:<span class="hljs-literal">true</span>}
});
<span class="hljs-built_in">module</span>.exports={
    User
}
</code></pre>
<h3 id="t184.4 routes/user.js">4.4 routes/user.js <a href="#t184.4 routes/user.js"> # </a></h3>
<p>server/routes/user.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> express=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express&apos;</span>);
<span class="hljs-keyword">let</span> router=express.Router();
<span class="hljs-keyword">let</span> axios=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;axios&apos;</span>);
<span class="hljs-keyword">let</span> {SMS}=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../config&apos;</span>);
<span class="hljs-keyword">const</span> {User}=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../models&apos;</span>);
router.get(<span class="hljs-string">&apos;/getCaptcha&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> {mobile}=req.query;
    <span class="hljs-keyword">let</span> captcha=<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getMilliseconds();
    req.session.mobile=mobile;
    req.session.captcha=captcha;
    <span class="hljs-keyword">let</span> {data} = <span class="hljs-keyword">await</span> axios({
        <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
        <span class="hljs-attr">url</span>: <span class="hljs-string">&apos;https://open.ucpaas.com/ol/sms/sendsms&apos;</span>,
        <span class="hljs-attr">data</span>: {
            ...SMS,
            mobile,
            <span class="hljs-attr">param</span>:captcha,
        },
        <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">&quot;Content-Type&quot;</span>: <span class="hljs-string">&quot;application/json;charset=utf-8&quot;</span>,
            <span class="hljs-string">&quot;Accept&quot;</span>: <span class="hljs-string">&quot;application/json&quot;</span>
        }
    });
    <span class="hljs-keyword">if</span> (data.code == <span class="hljs-string">&apos;000000&apos;</span>) {
        res.json({<span class="hljs-attr">code</span>: <span class="hljs-number">0</span>,<span class="hljs-attr">data</span>:captcha});
    } <span class="hljs-keyword">else</span> {

        res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">1</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;error&apos;</span>});
    } 
});

router.post(<span class="hljs-string">&apos;/register&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> {email,password,mobile,captcha}=req.body;
    <span class="hljs-keyword">if</span> (req.session.captcha != captcha) {
        <span class="hljs-keyword">return</span> res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">0</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;&#x9A8C;&#x8BC1;&#x7801;&#x9519;&#x8BEF;!&apos;</span>});
    }
    <span class="hljs-keyword">let</span> user=<span class="hljs-keyword">new</span> User({email,password,mobile});
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> user.save();
        res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">0</span>,<span class="hljs-attr">data</span>:<span class="hljs-string">&apos;&#x6CE8;&#x518C;&#x6210;&#x529F;&apos;</span>});
    } <span class="hljs-keyword">catch</span> (error) {
        res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">1</span>,error});
    }
});
router.post(<span class="hljs-string">&apos;/login&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> {email,password,captcha,type}=req.body;
    <span class="hljs-keyword">if</span> (type==<span class="hljs-string">&apos;mobile&apos;</span>) {
        <span class="hljs-keyword">if</span> (req.session.captcha != captcha) {
            <span class="hljs-keyword">return</span> res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">0</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;&#x767B;&#x5F55;&#x5931;&#x8D25;!&apos;</span>});
        }
        <span class="hljs-keyword">let</span> mobile=req.session.mobile;
        <span class="hljs-built_in">console</span>.log(mobile,req.session.captcha , captcha);
        <span class="hljs-keyword">let</span> oldUser=<span class="hljs-keyword">await</span> User.findOne({mobile});
        <span class="hljs-keyword">if</span> (oldUser) {
            req.session.user=oldUser;
            res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">0</span>,<span class="hljs-attr">data</span>:<span class="hljs-string">&apos;&#x767B;&#x5F55;&#x6210;&#x529F;&apos;</span>});
        } <span class="hljs-keyword">else</span> {
            res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">1</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;&#x7528;&#x6237;&#x540D;&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;&apos;</span>});
        }
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">let</span> oldUser=<span class="hljs-keyword">await</span> User.findOne({email,password});
        <span class="hljs-keyword">if</span> (oldUser) {
            req.session.user=oldUser;
            res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">0</span>,<span class="hljs-attr">data</span>:<span class="hljs-string">&apos;&#x767B;&#x5F55;&#x6210;&#x529F;&apos;</span>});
        } <span class="hljs-keyword">else</span> {
            res.json({<span class="hljs-attr">code</span>:<span class="hljs-number">1</span>,<span class="hljs-attr">error</span>:<span class="hljs-string">&apos;&#x7528;&#x6237;&#x540D;&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;&apos;</span>});
        }
    }
});
<span class="hljs-built_in">module</span>.exports=router;
</code></pre>
<h3 id="t194.5 Rooms/index.jsx">4.5 Rooms/index.jsx <a href="#t194.5 Rooms/index.jsx"> # </a></h3>
<p>src/pages/Rooms/index.jsx</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rooms</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span></span>{
    render(){
        <span class="hljs-keyword">return</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Rooms<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
        )    
    }
}
</code></pre>
<h3 id="t204.6 User/Login.jsx">4.6 User/Login.jsx <a href="#t204.6 User/Login.jsx"> # </a></h3>
<p>src/pages/User/Login.jsx</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/link&apos;</span>;
<span class="hljs-keyword">import</span> {
    Form,
    Input,
    Button,
    Select,
    Row,
    Col,
    Popover,
    Progress,
    Tabs
} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./Login.less&apos;</span>;
<span class="hljs-keyword">const</span> FormItem=Form.Item;
<span class="hljs-keyword">const</span> {Option}=Select;
<span class="hljs-keyword">const</span> InputGroup=Input.Group;
<span class="hljs-keyword">const</span> TabPane = Tabs.TabPane;

@connect(<span class="hljs-function">(<span class="hljs-params">{register,loading}</span>) =&gt;</span> ({register,<span class="hljs-attr">submitting</span>: loading.effects[<span class="hljs-string">&apos;register/submit&apos;</span>]}))
@Form.create()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    state={
        <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">type</span>:<span class="hljs-string">&apos;account&apos;</span>
    };

    onGetCaptcha=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> {dispatch,form}=<span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">let</span> mobile=form.getFieldValue(<span class="hljs-string">&apos;mobile&apos;</span>);
        dispatch({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;register/getCaptcha&apos;</span>,<span class="hljs-attr">payload</span>: mobile});
        <span class="hljs-keyword">let</span> count=<span class="hljs-number">59</span>;
        <span class="hljs-keyword">this</span>.setState({count});
        <span class="hljs-keyword">this</span>.interval=setInterval(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
            count-=<span class="hljs-number">1</span>;
            <span class="hljs-keyword">this</span>.setState({count});
            <span class="hljs-keyword">if</span> (count===<span class="hljs-number">0</span>) {
                clearInterval(<span class="hljs-keyword">this</span>.interval);
            }
        },<span class="hljs-number">1000</span>);
    };
    handleSubmit=<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
        e.preventDefault();
        <span class="hljs-keyword">const</span> {form,dispatch}=<span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> {type}=<span class="hljs-keyword">this</span>.state;
        form.validateFields({
            <span class="hljs-attr">force</span>: <span class="hljs-literal">true</span>
        },(err,values) =&gt; {
            <span class="hljs-keyword">if</span> (!err) {
                dispatch({
                    <span class="hljs-attr">type</span>: <span class="hljs-string">&apos;login/submit&apos;</span>,
                    <span class="hljs-attr">payload</span>: {
                        ...values,
                        type
                    }
                });
            }
        });
    };
    onSwitch = <span class="hljs-function"><span class="hljs-params">type</span> =&gt;</span> {
        <span class="hljs-keyword">this</span>.setState({
          type,
        });
    };
    render() {
        <span class="hljs-keyword">const</span> {form,submitting}=<span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> {getFieldDecorator}=form;
        <span class="hljs-keyword">const</span> {count}=<span class="hljs-keyword">this</span>.state;
        <span class="hljs-keyword">return</span> (
            &lt;div className={styles.register}&gt;
                &lt;h3&gt;&#x7528;&#x6237;&#x6CE8;&#x518C;&lt;/h3&gt;
                &lt;Form onSubmit={this.handleSubmit}&gt;
                    &lt;Tabs defaultActiveKey=&quot;account&quot; onChange={this.onSwitch}&gt;
                      &lt;TabPane tab=&quot;&#x8D26;&#x53F7;&#x5BC6;&#x7801;&#x767B;&#x5F55;&quot; key=&quot;account&quot;&gt;
                        &lt;FormItem&gt;
                            {getFieldDecorator(&apos;email&apos;,{
                                rules: [
                                    {
                                        required: true,
                                        message: &apos;&#x90AE;&#x7BB1;&#x5FC5;&#x987B;&#x8F93;&#x5165;&apos;
                                    },{
                                        type: &apos;email&apos;,
                                        message: &apos;&#x90AE;&#x7BB1;&#x683C;&#x5F0F;&#x4E0D;&#x5408;&#x6CD5;&apos;
                                    }
                                ]
                            })(&lt;Input size=&quot;large&quot; placeholder=&quot;&#x90AE;&#x7BB1;&quot; /&gt;)}
                        &lt;/FormItem&gt;
                        &lt;FormItem&gt;
                            {getFieldDecorator(&apos;password&apos;,{
                                rules: [
                                    {
                                        required: true,
                                        message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x5BC6;&#x7801;&#xFF01;&apos;
                                    }
                                ]
                            })(&lt;Input size=&quot;large&quot; type=&quot;password&quot; placeholder=&quot;&#x5BC6;&#x7801;&quot; /&gt;)}
                        &lt;/FormItem&gt;
                    &lt;/TabPane&gt;
...
</code></pre>
<h3 id="t214.7 User/Login.less">4.7 User/Login.less <a href="#t214.7 User/Login.less"> # </a></h3>
<p>src/pages/User/Login.less</p>
<pre><code class="lang-less"><span class="hljs-selector-class">.register</span>{
    <span class="hljs-attribute">width</span>:<span class="hljs-number">450px</span>;
    <span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid <span class="hljs-number">#CCC</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">padding</span>:<span class="hljs-number">20px</span>;
    <span class="hljs-selector-tag">h3</span>{
        <span class="hljs-attribute">text-align</span>: center;
    }
    <span class="hljs-selector-class">.getCaptcha</span>{
        <span class="hljs-attribute">width</span>:<span class="hljs-number">100%</span>;
        <span class="hljs-attribute">display</span>:block;
    }
    <span class="hljs-selector-class">.toRegister</span>{
        <span class="hljs-attribute">float</span>:right;
    }
}
</code></pre>
<h3 id="t224.8 User/Register.jsx">4.8 User/Register.jsx <a href="#t224.8 User/Register.jsx"> # </a></h3>
<p>src/pages/User/Register.jsx</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/link&apos;</span>;
<span class="hljs-keyword">import</span> {
    Form,
    Input,
    Button,
    Select,
    Row,
    Col,
    Popover,
    Progress
} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./Register.less&apos;</span>;
<span class="hljs-keyword">const</span> FormItem=Form.Item;
<span class="hljs-keyword">const</span> {Option}=Select;
<span class="hljs-keyword">const</span> InputGroup=Input.Group;

<span class="hljs-keyword">const</span> passwordStatusMap={
    <span class="hljs-attr">ok</span>: (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.success}</span>&gt;</span>
            &#x5F3A;&#x5EA6;: &#x5F3A;
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    ),
    <span class="hljs-attr">pass</span>: (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.warning}</span>&gt;</span>
            v&#x5F3A;&#x5EA6;: &#x4E2D;
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    ),
    <span class="hljs-attr">poor</span>: (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.error}</span>&gt;</span>
            &#x5F3A;&#x5EA6;: &#x592A;&#x77ED;
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
};
<span class="hljs-keyword">const</span> passwordProgressMap={
    <span class="hljs-attr">ok</span>: <span class="hljs-string">&apos;success&apos;</span>,
    <span class="hljs-attr">pass</span>: <span class="hljs-string">&apos;normal&apos;</span>,
    <span class="hljs-attr">poor</span>: <span class="hljs-string">&apos;exception&apos;</span>
};

@connect(<span class="hljs-function">(<span class="hljs-params">{register,loading}</span>) =&gt;</span> ({register,<span class="hljs-attr">submitting</span>: loading.effects[<span class="hljs-string">&apos;register/submit&apos;</span>]}))
@Form.create()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    state={
        <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">confirmDirty</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">visible</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">help</span>: <span class="hljs-string">&apos;&apos;</span>,
        <span class="hljs-attr">prefix</span>: <span class="hljs-string">&apos;86&apos;</span>
    };
    getPasswordStatus=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> {form}=<span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> value=form.getFieldValue(<span class="hljs-string">&apos;password&apos;</span>);
        <span class="hljs-keyword">if</span> (value&amp;&amp;value.length&gt;<span class="hljs-number">9</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;ok&apos;</span>;
        }
        <span class="hljs-keyword">if</span> (value&amp;&amp;value.length&gt;<span class="hljs-number">5</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;pass&apos;</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-string">&apos;poor&apos;</span>;
    };

    renderPasswordProgress=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> {form}=<span class="hljs-keyword">this</span>.props;
        <span class="hljs-keyword">const</span> value=form.getFieldValue(<span class="hljs-string">&apos;password&apos;</span>);
        <span class="hljs-keyword">const</span> passwordStatus=<span class="hljs-keyword">this</span>.getPasswordStatus();
        <span class="hljs-keyword">return</span> value&amp;&amp;value.length
            ? (
                &lt;div className={styles[`progress-${passwordStatus}`]}&gt;
                    &lt;Progress
                        status={passwordProgressMap[passwordStatus]}
                        className={styles.progress}
                        strokeWidth={6}
                        percent={value.length*10&gt;100
                            ? 100
                            :value.length*10}
                        showInfo={false} /&gt;
                &lt;/div&gt;
            )
            :null;
    };

    checkPassword=(rule,value,callback) =&gt; {
        const {visible,confirmDirty}=this.state;
        if (!value) {
            this.setState({
                help: &quot;&#x8BF7;&#x8F93;&#x5165;&#x5BC6;&#x7801;!&quot;,
                visible: !!value
            });
            callback(&apos;error&apos;);
        } else {
            this.setState({help: &apos;&apos;});
            if (!visible) {
                this.setState({
                    visible: !!value
                });
            }
            if (value.length&lt;6) {
                callback(&apos;error&apos;);
            } else {
                const {form}=this.props;
                if (value&amp;&amp;confirmDirty) {
                    form.validateFields([&apos;confirm&apos;],{force: true});
                }
                callback();
            }
        }
    };
    checkConfirm=(rule,value,callback) =&gt; {
        const {form}=this.props;
        if (value&amp;&amp;value!==form.getFieldValue(&apos;password&apos;)) {
            callback(&apos;&#x4E24;&#x6B21;&#x8F93;&#x5165;&#x7684;&#x5BC6;&#x7801;&#x4E0D;&#x5339;&#x914D;!&apos;);
        } else {
            callback();
        }
    };
    changePrefix=value =&gt; {
        this.setState({prefix: value});
    };
    onGetCaptcha=() =&gt; {
        const {dispatch,form}=this.props;
        let mobile=form.getFieldValue(&apos;mobile&apos;);
        dispatch({type: &apos;register/getCaptcha&apos;,payload: mobile});
        let count=59;
        this.setState({count});
        this.interval=setInterval(() =&gt; {
            count-=1;
            this.setState({count});
            if (count===0) {
                clearInterval(this.interval);
            }
        },1000);
    };
    handleSubmit=e =&gt; {
        e.preventDefault();
        const {form,dispatch}=this.props;
        form.validateFields({
            force: true
        },(err,values) =&gt; {
            console.log(&apos;values&apos;,values);
            if (!err) {
                const {prefix}=this.state;
                dispatch({
                    type: &apos;register/submit&apos;,
                    payload: {
                        ...values,
                        prefix
                    }
                });
            }
        });
    };
    render() {
        const {form,submitting}=this.props;
        const {getFieldDecorator}=form;
        const {count,prefix,help,visible}=this.state;
        return (
            &lt;div className={styles.register}&gt;
                &lt;h3&gt;&#x7528;&#x6237;&#x6CE8;&#x518C;&lt;/h3&gt;
                &lt;Form onSubmit={this.handleSubmit}&gt;
                    &lt;FormItem&gt;
                        {getFieldDecorator(&apos;email&apos;,{
                            rules: [
                                {
                                    required: true,
                                    message: &apos;&#x90AE;&#x7BB1;&#x5FC5;&#x987B;&#x8F93;&#x5165;&apos;
                                },{
                                    type: &apos;email&apos;,
                                    message: &apos;&#x90AE;&#x7BB1;&#x683C;&#x5F0F;&#x4E0D;&#x5408;&#x6CD5;&apos;
                                }
                            ]
                        })(&lt;Input size=&quot;large&quot; placeholder=&quot;&#x90AE;&#x7BB1;&quot; /&gt;)}
                    &lt;/FormItem&gt;
                    &lt;FormItem help={help}&gt;
                        &lt;Popover
                            content={
                                &lt;div style={{padding: &apos;4px 0&apos;}}&gt;
                                    {passwordStatusMap[this.getPasswordStatus()]}
                                    {this.renderPasswordProgress()}
                                    &lt;div style={{marginTop: 10}}&gt;
                                      &#x8BF7;&#x81F3;&#x5C11;&#x8F93;&#x5165; 6 &#x4E2A;&#x5B57;&#x7B26;&#x3002;&#x8BF7;&#x4E0D;&#x8981;&#x4F7F;&#x7528;&#x5BB9;&#x6613;&#x88AB;&#x731C;&#x5230;&#x7684;&#x5BC6;&#x7801;&#x3002;
                                    &lt;/div&gt;
                                &lt;/div&gt;
                            }
                            overlayStyle={{width: 240}}
                            placement=&quot;right&quot;
                            visible={visible}
                        &gt;
                            {getFieldDecorator(&apos;password&apos;,{
                                rules: [
                                    {
                                        validator: this.checkPassword
                                    }
                                ]
                            })(&lt;Input size=&quot;large&quot; type=&quot;password&quot; placeholder=&apos;&#x81F3;&#x5C11;&#x516D;&#x4F4D;&#x5BC6;&#x7801;&#xFF0C;&#x533A;&#x5206;&#x5927;&#x5C0F;&#x5199;&apos; /&gt;)}
                        &lt;/Popover&gt;
                    &lt;/FormItem&gt;
                    &lt;FormItem&gt;
                        {getFieldDecorator(&apos;confirm&apos;,{
                            rules: [
                                {
                                    required: true,
                                    message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x786E;&#x8BA4;&#x5BC6;&#x7801;&#xFF01;&apos;
                                },{
                                    validator: this.checkConfirm
                                }
                            ]
                        })(&lt;Input size=&quot;large&quot; type=&quot;password&quot; placeholder=&quot;&#x786E;&#x8BA4;&#x5BC6;&#x7801;&quot; /&gt;)}
                    &lt;/FormItem&gt;
                    &lt;FormItem&gt;
                        &lt;InputGroup compact&gt;
                            &lt;Select
                                size=&quot;large&quot;
                                value={prefix}
                                onChange={this.changePrefix}
                                style={{
                                    width: &apos;20%&apos;
                                }}&gt;
                                &lt;Option value=&quot;86&quot;&gt;+86&lt;/Option&gt;
                                &lt;Option value=&quot;87&quot;&gt;+87&lt;/Option&gt;
                            &lt;/Select&gt;
                            {getFieldDecorator(&apos;mobile&apos;,{
                                rules: [
                                    {
                                        required: true,
                                        message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x624B;&#x673A;&#x53F7;!&apos;
                                    },{
                                        pattern: /^\d{11}$/,
                                        message: &apos;&#x624B;&#x673A;&#x53F7;&#x683C;&#x5F0F;&#x9519;&#x8BEF;&#xFF01;&apos;
                                    }
                                ]
                            })(&lt;Input
                                size=&quot;large&quot;
                                style={{
                                    width: &apos;80%&apos;
                                }}
                                placeholder=&apos;&#x624B;&#x673A;&#x53F7;&apos; /&gt;)}
                        &lt;/InputGroup&gt;
                    &lt;/FormItem&gt;
                    &lt;FormItem&gt;
                        &lt;Row gutter={8}&gt;
                            &lt;Col span={16}&gt;
                                {getFieldDecorator(&apos;captcha&apos;,{
                                    rules: [
                                        {
                                            required: true,
                                            message: &apos;&#x8BF7;&#x8F93;&#x5165;&#x9A8C;&#x8BC1;&#x7801;&#xFF01;&apos;
                                        }
                                    ]
                                })(&lt;Input size=&quot;large&quot; placeholder=&quot;&#x9A8C;&#x8BC1;&#x7801;&quot; /&gt;)}
                            &lt;/Col&gt;
                            &lt;Col span={8}&gt;
                                &lt;Button
                                    size=&quot;large&quot;
                                    disabled={count}
                                    className={styles.getCaptcha}
                                    onClick={this.onGetCaptcha}&gt;
                                    {count
                                        ? `${count} s`
                                        :&apos;&#x83B7;&#x53D6;&#x9A8C;&#x8BC1;&#x7801;&apos;}
                                &lt;/Button&gt;
                            &lt;/Col&gt;
                        &lt;/Row&gt;
                    &lt;/FormItem&gt;
                    &lt;FormItem&gt;
                        &lt;Button
                            size=&quot;large&quot;
                            loading={submitting}
                            className={styles.submit}
                            type=&quot;primary&quot;
                            htmlType=&quot;submit&quot;&gt;
                            &#x6CE8;&#x518C;
                                                &lt;/Button&gt;
                        &lt;Link className={styles.login} to=&quot;/User/Login&quot;&gt;
                            &#x4F7F;&#x7528;&#x5DF2;&#x6709;&#x8D26;&#x6237;&#x767B;&#x5F55;
                                                &lt;/Link&gt;
                    &lt;/FormItem&gt;
                &lt;/Form&gt;
            &lt;/div&gt;

        );
    }
}
</code></pre>
<h3 id="t234.9 models/login.js">4.9 models/login.js <a href="#t234.9 models/login.js"> # </a></h3>
<p>src/pages/User/models/login.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> loginService <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../services/login&apos;</span>;
<span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/router&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">namespace</span>: <span class="hljs-string">&apos;login&apos;</span>,

  <span class="hljs-attr">state</span>: {

  },

  <span class="hljs-attr">effects</span>: {
      *getCaptcha({payload},{call,put}) {
         <span class="hljs-keyword">yield</span> call(loginService.getCaptcha,payload);
    },
    *submit({payload},{call,put}) {
      <span class="hljs-keyword">let</span> {code}=<span class="hljs-keyword">yield</span> call(loginService.submit,payload);
      <span class="hljs-keyword">if</span>(code == <span class="hljs-number">0</span>)
        router.push(<span class="hljs-string">&apos;/Rooms&apos;</span>);
    }
  },

  <span class="hljs-attr">reducers</span>: {

  },
};
</code></pre>
<h3 id="t244.10 models/register.js">4.10 models/register.js <a href="#t244.10 models/register.js"> # </a></h3>
<p>src/pages/User/models/register.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> registerService <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../services/register&apos;</span>;
<span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/router&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">namespace</span>: <span class="hljs-string">&apos;register&apos;</span>,

  <span class="hljs-attr">state</span>: {

  },

  <span class="hljs-attr">effects</span>: {
      *getCaptcha({payload},{call,put}) {
         <span class="hljs-keyword">yield</span> call(registerService.getCaptcha,payload);
    },
    *submit({payload},{call,put}) {
      <span class="hljs-keyword">yield</span> call(registerService.submit,payload);
      router.push(<span class="hljs-string">&apos;/User/Login&apos;</span>);
    }
  },

  <span class="hljs-attr">reducers</span>: {

  },
};
</code></pre>
<h3 id="t254.11 services/login.js">4.11 services/login.js <a href="#t254.11 services/login.js"> # </a></h3>
<p>src/pages/User/services/login.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../../../utils/request&apos;</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCaptcha</span>(<span class="hljs-params">mobile</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/user/getCaptcha?mobile=<span class="hljs-subst">${mobile}</span>`</span>);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">submit</span>(<span class="hljs-params">values</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/user/login`</span>,{
    <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(values),
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">&apos;Content-Type&apos;</span>: <span class="hljs-string">&quot;application/json&quot;</span>,
      <span class="hljs-string">&quot;Accept&quot;</span>:<span class="hljs-string">&quot;application/json&apos;&quot;</span>
    }
  });
}
</code></pre>
<h3 id="t264.12 services/register.js">4.12 services/register.js <a href="#t264.12 services/register.js"> # </a></h3>
<p>src/pages/User/services/register.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">submit</span>(<span class="hljs-params">values</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/user/register`</span>,{
    <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(values),
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">&apos;Content-Type&apos;</span>: <span class="hljs-string">&quot;application/json&quot;</span>,
      <span class="hljs-string">&quot;Accept&quot;</span>:<span class="hljs-string">&quot;application/json&apos;&quot;</span>
    }
  });
}
</code></pre>
<h3 id="t274.13 utils/request.js">4.13 utils/request.js <a href="#t274.13 utils/request.js"> # </a></h3>
<p>src/utils/request.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-  return fetch(HOST+url, options)</span>
<span class="hljs-addition">+  return fetch(HOST+url,{</span>
<span class="hljs-addition">+    ...options,</span>
<span class="hljs-addition">+    credentials:&apos;include&apos;</span>
<span class="hljs-addition">+  })</span>
</code></pre>
<h2 id="t285. &#x5B9E;&#x73B0;&#x623F;&#x95F4;&#x529F;&#x80FD;">5. &#x5B9E;&#x73B0;&#x623F;&#x95F4;&#x529F;&#x80FD; <a href="#t285. &#x5B9E;&#x73B0;&#x623F;&#x95F4;&#x529F;&#x80FD;"> # </a></h2>
<h3 id="t295.1 server/app.js">5.1 server/app.js <a href="#t295.1 server/app.js"> # </a></h3>
<p>server/app.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+ let room=require(&apos;./routes/room&apos;);</span>
app.use(&apos;/user&apos;,user);
<span class="hljs-addition">+ app.use(&apos;/room&apos;,room);</span>
</code></pre>
<h3 id="t305.2 models/index.js">5.2 models/index.js <a href="#t305.2 models/index.js"> # </a></h3>
<p>server/models/index.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+</span>
<span class="hljs-addition">+const Room = conn.model(&apos;Room&apos;, {</span>
<span class="hljs-addition">+    name: {type: String,required: true}</span>
<span class="hljs-addition">+});</span>
<span class="hljs-addition">+</span>
 module.exports={
<span class="hljs-deletion">-    User</span>
<span class="hljs-addition">+    User,</span>
<span class="hljs-addition">+    Room</span>
 }
</code></pre>
<h3 id="t315.3 routes/room.js">5.3 routes/room.js <a href="#t315.3 routes/room.js"> # </a></h3>
<p>server/routes/room.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> express=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express&apos;</span>);
<span class="hljs-keyword">let</span> router=express.Router();
<span class="hljs-keyword">const</span> {Room}=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../models&apos;</span>);

router.get(<span class="hljs-string">&apos;/list&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> list = <span class="hljs-keyword">await</span> Room.find();
    res.json({
        <span class="hljs-attr">code</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">data</span>:list
    });
});

router.post(<span class="hljs-string">&apos;/create&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req,res</span>) </span>{
    <span class="hljs-keyword">let</span> {name}=req.body;
    <span class="hljs-keyword">await</span> Room.create({name});
    res.json({
        <span class="hljs-attr">code</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">data</span>:<span class="hljs-string">&apos;&#x623F;&#x95F4;&#x521B;&#x5EFA;&#x6210;&#x529F;&apos;</span>
    });
});

<span class="hljs-built_in">module</span>.exports=router;
</code></pre>
<h3 id="t325.4 Room/index.jsx">5.4 Room/index.jsx <a href="#t325.4 Room/index.jsx"> # </a></h3>
<p>src/pages/Room/index.jsx</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/link&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> {Layout,Menu,Card,Input,Row,Col,Button,Form} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./index.less&apos;</span>;
<span class="hljs-keyword">const</span> {Header,Footer,Content}=Layout;

@connect(<span class="hljs-function">(<span class="hljs-params">{room,loading}</span>) =&gt;</span> ({room,<span class="hljs-attr">loading</span>: loading.effects[<span class="hljs-string">&apos;room/list&apos;</span>]}))
@Form.create()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rooms</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    createRoom=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">let</span> name=<span class="hljs-keyword">this</span>.props.form.getFieldValue(<span class="hljs-string">&apos;keyword&apos;</span>);
        <span class="hljs-keyword">if</span> (name) {
            <span class="hljs-keyword">this</span>.props.dispatch({
                <span class="hljs-attr">type</span>: <span class="hljs-string">&apos;room/create&apos;</span>,
                <span class="hljs-attr">payload</span>:{name}
            });
        }
    }
    render() {
        <span class="hljs-keyword">let</span> name=<span class="hljs-keyword">this</span>.props.form.getFieldValue(<span class="hljs-string">&apos;keyword&apos;</span>);
        <span class="hljs-keyword">let</span> rooms=<span class="hljs-keyword">this</span>.props.room.list;
        <span class="hljs-keyword">if</span> (name) {
            rooms = rooms.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.name.indexOf(name)!=<span class="hljs-number">-1</span>);
        }

        <span class="hljs-keyword">return</span> (
            &lt;Layout&gt;
                &lt;Header&gt;
                    &lt;a className={styles.logo}&gt;&#x73E0;&#x5CF0;&#x804A;&#x5929;&#x5BA4;&lt;/a&gt;
                    &lt;Menu
                        theme=&quot;dark&quot;
                        mode=&quot;horizontal&quot;
                        defaultSelectedKeys={[&apos;register&apos;]}
                        style={{ lineHeight: &apos;64px&apos; }}
                    &gt;
                        &lt;Menu.Item key=&quot;register&quot;&gt;&#x6CE8;&#x518C;&lt;/Menu.Item&gt;
                        &lt;Menu.Item key=&quot;login&quot;&gt;&#x767B;&#x5F55;&lt;/Menu.Item&gt;
                    &lt;/Menu&gt;
                &lt;/Header&gt;
                &lt;Content&gt;
                    &lt;Card&gt;
                        &lt;Row gutter={16}&gt;
                            &lt;Col span={6} offset={8}&gt;
                                {
                                    this.props.form.getFieldDecorator(&apos;keyword&apos;)(
                                        &lt;Input type=&quot;text&quot; placeholder=&quot;&#x8BF7;&#x8F93;&#x5165;&#x623F;&#x95F4;&#x540D;&quot;&gt;&lt;/Input&gt;
                                    )
                                }
                            &lt;/Col&gt;
                        &lt;/Row&gt;                
                    &lt;/Card&gt;
                    &lt;Card&gt;
                        &lt;Row gutter={16}&gt;
                            {
                                rooms.length&gt;0?rooms.map(item =&gt; (
                                    &lt;Col span={6} key={item._id}&gt;
                                        &lt;Card
                                            title={item.name}
                                            extra={&lt;Link to={`/Rooms/${item._id}`}&gt;&#x8FDB;&#x5165;&lt;/Link&gt;}
                                        &gt;
                                            &lt;p&gt;&#x7528;&#x6237;1&lt;/p&gt;
                                            &lt;p&gt;&#x7528;&#x6237;2&lt;/p&gt;
                                            &lt;p&gt;&#x7528;&#x6237;3&lt;/p&gt;
                                        &lt;/Card&gt;
                                    &lt;/Col&gt;    
                                )):&lt;Button onClick={this.createRoom}&gt;&#x521B;&#x5EFA;&#x623F;&#x95F4;&lt;/Button&gt;
                            }
                        &lt;/Row&gt;
                    &lt;/Card&gt;
                &lt;/Content&gt;
                &lt;Footer&gt;
                    &lt;div className={styles.copyright}&gt; &#xA9;2018 &#x73E0;&#x5CF0;&#x57F9;&#x8BAD;&lt;/div&gt;
                &lt;/Footer&gt;
            &lt;/Layout&gt;
        )
    }
}
</code></pre>
<h3 id="t335.5 Room/index.less">5.5 Room/index.less <a href="#t335.5 Room/index.less"> # </a></h3>
<p>src/pages/Room/index.less</p>
<pre><code class="lang-less"><span class="hljs-selector-class">.logo</span>{
    <span class="hljs-attribute">width</span>:<span class="hljs-number">120px</span>;
    <span class="hljs-attribute">height</span>:<span class="hljs-number">64px</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">64px</span>;
    <span class="hljs-attribute">float</span>:left;
}

<span class="hljs-selector-class">.copyright</span>{
    <span class="hljs-attribute">text-align</span>:center;
}
</code></pre>
<h3 id="t345.6 models/room.js">5.6 models/room.js <a href="#t345.6 models/room.js"> # </a></h3>
<p>src/pages/Room/models/room.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> roomService <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../services/room&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {

  <span class="hljs-attr">namespace</span>: <span class="hljs-string">&apos;room&apos;</span>,

  <span class="hljs-attr">state</span>: {
    <span class="hljs-attr">list</span>: []
  },

  <span class="hljs-attr">subscriptions</span>: {
    setup({ dispatch, history }) {
      history.listen(<span class="hljs-function">(<span class="hljs-params">{pathname,query}</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span>(pathname == <span class="hljs-string">&apos;/Room&apos;</span>){
          dispatch({
            <span class="hljs-attr">type</span>:<span class="hljs-string">&apos;getRooms&apos;</span>
          });
        }
      });
    },
  },

  <span class="hljs-attr">effects</span>: {
    *getRooms({ payload }, { call, put }) {
      <span class="hljs-keyword">let</span> {<span class="hljs-attr">data</span>: list}=<span class="hljs-keyword">yield</span> call(roomService.getRooms);
      <span class="hljs-keyword">yield</span> put({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;save&apos;</span>,<span class="hljs-attr">payload</span>: {list}});
    },
    *create({ payload }, { call, put }) {
      <span class="hljs-keyword">yield</span> call(roomService.create,payload);
      <span class="hljs-keyword">yield</span> put({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;getRooms&apos;</span>});
    }
  },

  <span class="hljs-attr">reducers</span>: {
    save(state, action) {
      <span class="hljs-keyword">return</span> { ...state, ...action.payload };
    },
  },
};
</code></pre>
<h3 id="t355.7 services/room.js">5.7 services/room.js <a href="#t355.7 services/room.js"> # </a></h3>
<p>src/pages/Room/services/room.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../../../utils/request&apos;</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRooms</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/room/list`</span>);
}
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">create</span>(<span class="hljs-params">values</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/room/create`</span>,{
    <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(values),
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">&apos;Content-Type&apos;</span>: <span class="hljs-string">&quot;application/json&quot;</span>,
      <span class="hljs-string">&quot;Accept&quot;</span>:<span class="hljs-string">&quot;application/json&apos;&quot;</span>
    }
  });
}
</code></pre>
<h2 id="t366. &#x5B9E;&#x73B0;&#x804A;&#x5929;&#x529F;&#x80FD;">6. &#x5B9E;&#x73B0;&#x804A;&#x5929;&#x529F;&#x80FD; <a href="#t366. &#x5B9E;&#x73B0;&#x804A;&#x5929;&#x529F;&#x80FD;"> # </a></h2>
<h3 id="t376.1 server/app.js">6.1 server/app.js <a href="#t376.1 server/app.js"> # </a></h3>
<p>server/app.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> express=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express&apos;</span>);
<span class="hljs-keyword">let</span> session=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;express-session&apos;</span>);
<span class="hljs-keyword">const</span> cors=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;cors&apos;</span>);
<span class="hljs-keyword">const</span> bodyParser=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;body-parser&apos;</span>);
<span class="hljs-keyword">const</span> {User,Room,Message}=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;./models&apos;</span>);
<span class="hljs-keyword">let</span> app=express();
app.use(cors({
    <span class="hljs-attr">origin</span>:<span class="hljs-string">&apos;http://localhost:8000&apos;</span>,
    <span class="hljs-attr">credentials</span>:<span class="hljs-literal">true</span>
}));
app.use(bodyParser.json());
app.use(session({
    <span class="hljs-attr">resave</span>:<span class="hljs-literal">true</span>,
    <span class="hljs-attr">secret</span>:<span class="hljs-string">&apos;zfpx&apos;</span>,
    <span class="hljs-attr">saveUninitialized</span>:<span class="hljs-literal">true</span>
}));
<span class="hljs-keyword">let</span> user=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;./routes/user&apos;</span>);
<span class="hljs-keyword">let</span> room=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;./routes/room&apos;</span>);
app.use(<span class="hljs-string">&apos;/user&apos;</span>,user);
app.use(<span class="hljs-string">&apos;/room&apos;</span>,room);
<span class="hljs-keyword">let</span> server=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;http&apos;</span>).createServer(app);
server.listen(<span class="hljs-number">3000</span>);
<span class="hljs-keyword">let</span> io=<span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;socket.io&apos;</span>)(server);
io.on(<span class="hljs-string">&apos;connection&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">socket</span>) </span>{
    <span class="hljs-keyword">let</span> userId=socket.handshake.query.user;<span class="hljs-comment">//&#x7528;&#x6237;</span>
    <span class="hljs-keyword">let</span> user=<span class="hljs-keyword">await</span> User.findById(userId);
    <span class="hljs-keyword">let</span> roomId=socket.handshake.query.room; <span class="hljs-comment">//&#x623F;&#x95F4;</span>
    <span class="hljs-comment">//&#x67E5;&#x627E;&#x623F;&#x95F4;</span>
    <span class="hljs-keyword">let</span> room=<span class="hljs-keyword">await</span> Room.findById(roomId);
    socket.join(roomId);<span class="hljs-comment">//&#x628A;&#x5F53;&#x524D;socket&#x6DFB;&#x52A0;&#x5230;&#x623F;&#x95F4;&#x91CC;</span>
    <span class="hljs-comment">//&#x628A;&#x7528;&#x6237;&#x653E;&#x5230;&#x623F;&#x95F4;&#x91CC;</span>
    <span class="hljs-keyword">await</span> User.findByIdAndUpdate(userId,{<span class="hljs-attr">room</span>: roomId});
    socket.on(<span class="hljs-string">&apos;getRoom&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">//&#x67E5;&#x627E;&#x623F;&#x95F4;&#x4E2D;&#x7684;&#x7528;&#x6237;</span>
        <span class="hljs-keyword">let</span> users=<span class="hljs-keyword">await</span> User.find({<span class="hljs-attr">room</span>: roomId});
        <span class="hljs-comment">//&#x67E5;&#x627E;&#x623F;&#x95F4;&#x91CC;&#x7684;&#x6D88;&#x606F;</span>
        <span class="hljs-keyword">let</span> messages = <span class="hljs-keyword">await</span> Message.find({<span class="hljs-attr">room</span>: roomId}); 
        socket.emit(<span class="hljs-string">&apos;room&apos;</span>,{room,users,messages});
    });
    socket.on(<span class="hljs-string">&apos;message&apos;</span>,<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">content</span>) </span>{
        <span class="hljs-keyword">let</span> {_id} = <span class="hljs-keyword">await</span> Message.create({
            <span class="hljs-attr">user</span>:userId,
            content,
            <span class="hljs-attr">room</span>:roomId
        });
        <span class="hljs-keyword">let</span> message=<span class="hljs-keyword">await</span> Message.findById(_id).populate(<span class="hljs-string">&apos;user&apos;</span>).populate(<span class="hljs-string">&apos;room&apos;</span>).exec();
        io.in(roomId).emit(<span class="hljs-string">&apos;message&apos;</span>,message);
    });

});
</code></pre>
<h3 id="t386.2 models/index.js">6.2 models/index.js <a href="#t386.2 models/index.js"> # </a></h3>
<p>server/models/index.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;mongoose&apos;</span>);
<span class="hljs-keyword">const</span> Schema = mongoose.Schema;
<span class="hljs-keyword">const</span> ObjectId = Schema.Types.ObjectId;
<span class="hljs-keyword">const</span> {DB} = <span class="hljs-built_in">require</span>(<span class="hljs-string">&apos;../config&apos;</span>);
<span class="hljs-keyword">const</span> conn = mongoose.createConnection(DB.url,{ <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
<span class="hljs-keyword">const</span> User = conn.model(<span class="hljs-string">&apos;User&apos;</span>, {
    <span class="hljs-attr">email</span>: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},        <span class="hljs-comment">//&#x90AE;&#x7BB1; </span>
    password: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},     <span class="hljs-comment">//&#x5BC6;&#x7801;</span>
    mobile: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},       <span class="hljs-comment">//&#x624B;&#x673A;&#x53F7;</span>
    avatar: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">false</span>},      <span class="hljs-comment">//&#x5934;&#x50CF;</span>
    createAt: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>,<span class="hljs-attr">default</span>: <span class="hljs-built_in">Date</span>.now},    <span class="hljs-comment">//&#x521B;&#x5EFA;&#x65F6;&#x95F4; </span>
    room:{<span class="hljs-attr">type</span>:ObjectId,<span class="hljs-attr">ref</span>:<span class="hljs-string">&apos;Room&apos;</span>}              <span class="hljs-comment">//&#x6240;&#x5C5E;&#x623F;&#x95F4;</span>
});

<span class="hljs-keyword">const</span> Room = conn.model(<span class="hljs-string">&apos;Room&apos;</span>, {
    <span class="hljs-attr">name</span>: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,<span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>},         <span class="hljs-comment">//&#x623F;&#x95F4;&#x540D;</span>
    avatar: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>},                      <span class="hljs-comment">//&#x623F;&#x95F4;&#x56FE;&#x7247;</span>
    createAt:{<span class="hljs-attr">type</span>:<span class="hljs-built_in">Date</span>,<span class="hljs-attr">default</span>:<span class="hljs-built_in">Date</span>.now}        <span class="hljs-comment">//&#x521B;&#x5EFA;&#x65F6;&#x95F4;</span>
});

<span class="hljs-keyword">const</span> Message = conn.model(<span class="hljs-string">&apos;Message&apos;</span>, {
    <span class="hljs-attr">content</span>: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>},                     <span class="hljs-comment">//&#x5185;&#x5BB9;</span>
    user: {<span class="hljs-attr">type</span>: ObjectId,<span class="hljs-attr">ref</span>: <span class="hljs-string">&apos;User&apos;</span>},          <span class="hljs-comment">//&#x7528;&#x6237;</span>
    createAt: {<span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>,<span class="hljs-attr">default</span>: <span class="hljs-built_in">Date</span>.now},    <span class="hljs-comment">//&#x521B;&#x5EFA;&#x65F6;&#x95F4; </span>
    room:{<span class="hljs-attr">type</span>:ObjectId,<span class="hljs-attr">ref</span>:<span class="hljs-string">&apos;Room&apos;</span>}              <span class="hljs-comment">//&#x623F;&#x95F4;</span>
});


<span class="hljs-built_in">module</span>.exports={
    User,
    Room,
    Message
}
</code></pre>
<h3 id="t396.3 routes/user.js">6.3 routes/user.js <a href="#t396.3 routes/user.js"> # </a></h3>
<p>server/routes/user.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+ const gravatar=require(&apos;gravatar&apos;);</span>
<span class="hljs-deletion">-    let user=new User({email,password,mobile});</span>
<span class="hljs-addition">+    let user=new User({email,password,mobile,avatar});</span>
<span class="hljs-deletion">-            res.json({code:0,data:&apos;&#x767B;&#x5F55;&#x6210;&#x529F;&apos;});</span>
<span class="hljs-addition">+            res.json({code:0,data:oldUser});</span>
<span class="hljs-deletion">-            res.json({code:0,data:&apos;&#x767B;&#x5F55;&#x6210;&#x529F;&apos;});</span>
<span class="hljs-addition">+            res.json({code:0,data:oldUser});</span>
</code></pre>
<h3 id="t406.4 Room/$id.jsx">6.4 Room/$id.jsx <a href="#t406.4 Room/$id.jsx"> # </a></h3>
<p>src/pages/Room/$id.jsx</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> {Layout,Menu,Card,Input,Row,Col,Button,Form,List,Avatar} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">const</span> {Header,Sider,Footer,Content}=Layout;
@connect(<span class="hljs-function">(<span class="hljs-params">{chat}</span>) =&gt;</span> ({chat}))
@Form.create()    
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Chat</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    talk=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">let</span> content=<span class="hljs-keyword">this</span>.props.form.getFieldValue(<span class="hljs-string">&apos;content&apos;</span>);
        <span class="hljs-keyword">this</span>.props.dispatch({
            <span class="hljs-attr">type</span>: <span class="hljs-string">&apos;chat/talk&apos;</span>,
            <span class="hljs-attr">payload</span>:content
        });
    }
    render() {
        <span class="hljs-keyword">let</span> {users,messages}=<span class="hljs-keyword">this</span>.props.chat;
        <span class="hljs-keyword">return</span> (
            &lt;Layout&gt;
                &lt;Header&gt;&lt;a href=&quot;#&quot;&gt;&#x73E0;&#x5CF0;&#x804A;&#x5929;&#x5BA4;&lt;/a&gt;&lt;/Header&gt;
                &lt;Layout&gt;
                    &lt;Sider&gt;
                        &lt;Menu
                            theme=&quot;dark&quot;
                            mode=&quot;vertical&quot;
                            defaultSelectedKeys={[]}
                        &gt;
                            {
                                users.map(user =&gt; (&lt;Menu.Item key={user._id}&gt;{user.email}&lt;/Menu.Item&gt;))
                            }
                        &lt;/Menu&gt;
                    &lt;/Sider&gt;
                    &lt;Content style={{height: &apos;600px&apos;}}&gt;
                        &lt;Card&gt;
                            &lt;List
                                itemLayout=&quot;horizontal&quot;
                                dataSource={messages}
                                renderItem={item =&gt; (
                                &lt;List.Item&gt;
                                    &lt;List.Item.Meta
                                        avatar={&lt;Avatar src={item.user.avatar} /&gt;}
                                        title={item.user.email}
                                        description={item.content}
                                    /&gt;
                                &lt;/List.Item&gt;
                            )}
                         /&gt;
                        &lt;/Card&gt;
                        &lt;Card&gt;
                            &lt;Row gutter={8}&gt;
                                &lt;Col span={23}&gt;
                                    {
                                        this.props.form.getFieldDecorator(&apos;content&apos;)(&lt;Input/&gt;)
                                    }
                                &lt;/Col&gt;
                                &lt;Col span={1}&gt;&lt;Button onClick={this.talk}&gt;&#x53D1;&#x8A00;&lt;/Button&gt;&lt;/Col&gt;
                            &lt;/Row&gt;
                        &lt;/Card&gt;
                    &lt;/Content&gt;
                &lt;/Layout&gt;
                &lt;Footer style={{textAlign:&apos;center&apos;}}&gt;
                        @2018 &#x73E0;&#x5CF0;&#x57F9;&#x8BAD;
                &lt;/Footer&gt;
            &lt;/Layout&gt;
        )
    }
}
</code></pre>
<h3 id="t416.5 Room/index.jsx">6.5 Room/index.jsx <a href="#t416.5 Room/index.jsx"> # </a></h3>
<p>src/pages/Room/index.jsx</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-     extra={&lt;Link to={`/Rooms/${item._id}`}&gt;&#x8FDB;&#x5165;&lt;/Link&gt;}</span>
<span class="hljs-addition">+     extra={&lt;Link to={`/Room/${item._id}`}&gt;&#x8FDB;&#x5165;&lt;/Link&gt;}</span>
</code></pre>
<h3 id="t426.6 models/chat.js">6.6 models/chat.js <a href="#t426.6 models/chat.js"> # </a></h3>
<p>src/pages/Room/models/chat.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> IO <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;socket.io-client&apos;</span>;
<span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/router&apos;</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">namespace</span>: <span class="hljs-string">&apos;chat&apos;</span>,

  <span class="hljs-attr">state</span>: {
    <span class="hljs-attr">room</span>: {},
    <span class="hljs-attr">users</span>: [],
    <span class="hljs-attr">messages</span>:[]
  },

  <span class="hljs-attr">subscriptions</span>: {
    setup({ dispatch, history }) {
      history.listen(<span class="hljs-function">(<span class="hljs-params">{pathname,query}</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> regexp=<span class="hljs-regexp">/\/Room\/([^/]+)$/</span>;
        <span class="hljs-keyword">let</span> result=pathname.match(regexp);
        <span class="hljs-keyword">if</span> (result) {
          <span class="hljs-keyword">let</span> roomId=result[<span class="hljs-number">1</span>];
          <span class="hljs-keyword">let</span> userStr = <span class="hljs-built_in">window</span>.sessionStorage.getItem(<span class="hljs-string">&apos;user&apos;</span>);
          <span class="hljs-keyword">if</span> (userStr) {
            <span class="hljs-keyword">let</span> user=<span class="hljs-built_in">JSON</span>.parse(userStr);
            <span class="hljs-keyword">const</span> socket= <span class="hljs-built_in">window</span>.socket = <span class="hljs-keyword">new</span> IO(<span class="hljs-string">&apos;http://localhost:3000&apos;</span>,{<span class="hljs-attr">query</span>:{<span class="hljs-attr">user</span>:user._id,<span class="hljs-attr">room</span>:roomId}});
            socket.on(<span class="hljs-string">&apos;room&apos;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">{room,users,messages}</span>) </span>{
                dispatch({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;save&apos;</span>,<span class="hljs-attr">payload</span>: {room,users,messages}});
            });
            socket.emit(<span class="hljs-string">&apos;getRoom&apos;</span>);
            socket.on(<span class="hljs-string">&apos;message&apos;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">message</span>) </span>{
              <span class="hljs-built_in">console</span>.log(message);
              dispatch({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;messageAdded&apos;</span>,<span class="hljs-attr">payload</span>:message});
            });
          } <span class="hljs-keyword">else</span> {
            router.push(<span class="hljs-string">&apos;/User/Login&apos;</span>);
          }
        } 
      });
    },
  },
  <span class="hljs-attr">effects</span>: {
    *talk({payload},{call,put,select}) {
      <span class="hljs-built_in">window</span>.socket.emit(<span class="hljs-string">&apos;message&apos;</span>,payload);
   }
  },
  <span class="hljs-attr">reducers</span>: {
    save(state, action) {
      <span class="hljs-keyword">return</span> { ...state, ...action.payload };
    },
    messageAdded(state,{payload}) {
      <span class="hljs-keyword">return</span> {...state, <span class="hljs-attr">messages</span>:[...state.messages,payload] };
    }
  }
};
</code></pre>
<h3 id="t436.7 models/room.js">6.7 models/room.js <a href="#t436.7 models/room.js"> # </a></h3>
<p>src/pages/Room/models/room.js</p>
<pre><code class="lang-js">-    dispatch({
-       type:<span class="hljs-string">&apos;getRooms&apos;</span>
-    });
+    dispatch({<span class="hljs-attr">type</span>:<span class="hljs-string">&apos;getRooms&apos;</span>});
</code></pre>
<h3 id="t446.8 models/login.js">6.8 models/login.js <a href="#t446.8 models/login.js"> # </a></h3>
<p>src/pages/User/models/login.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-      let {code}=yield call(loginService.submit,payload);</span>
<span class="hljs-deletion">-      if(code == 0)</span>
<span class="hljs-deletion">-        router.push(&apos;/Rooms&apos;);</span>
<span class="hljs-addition">+      let {code,data}=yield call(loginService.submit,payload);</span>
<span class="hljs-addition">+      if (code==0) {</span>
<span class="hljs-addition">+        yield put({type: &apos;save&apos;,payload: {user: data}});</span>
<span class="hljs-addition">+        window.sessionStorage.setItem(&apos;user&apos;,JSON.stringify(data));</span>
<span class="hljs-addition">+        router.push(&apos;/Room&apos;);</span>
<span class="hljs-addition">+      }</span>
</code></pre>
<h2 id="t457. &#x4E0A;&#x4F20;&#x56FE;&#x7247;">7. &#x4E0A;&#x4F20;&#x56FE;&#x7247; <a href="#t457. &#x4E0A;&#x4F20;&#x56FE;&#x7247;"> # </a></h2>
<h3 id="t467.1 server/app.js">7.1 server/app.js <a href="#t467.1 server/app.js"> # </a></h3>
<p>server/app.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-app.use(bodyParser.json());</span>
<span class="hljs-addition">+app.use(bodyParser.json({limit:&apos;1000kb&apos;}));</span>

<span class="hljs-deletion">-        let messages = await Message.find({room: roomId}); </span>
<span class="hljs-deletion">-        console.log(room,users,messages);</span>
<span class="hljs-addition">+        let messages = await Message.find({room: roomId}).populate(&apos;user&apos;);</span>
</code></pre>
<h3 id="t477.2 models/index.js">7.2 models/index.js <a href="#t477.2 models/index.js"> # </a></h3>
<p>server/models/index.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-    createAt:{type:Date,default:Date.now}        //&#x521B;&#x5EFA;&#x65F6;&#x95F4;</span>
<span class="hljs-addition">+    createAt: {type: Date,default: Date.now},        //&#x521B;&#x5EFA;&#x65F6;&#x95F4;</span>
<span class="hljs-addition">+    users:[{type:ObjectId,ref:&apos;User&apos;}]</span>
</code></pre>
<h3 id="t487.3 routes/room.js">7.3 routes/room.js <a href="#t487.3 routes/room.js"> # </a></h3>
<p>server/routes/room.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-const {Room}=require(&apos;../models&apos;);</span>
<span class="hljs-addition">+const {Room,User}=require(&apos;../models&apos;);</span>

<span class="hljs-deletion">-    let list = await Room.find();</span>
<span class="hljs-addition">+    let list=await Room.find();</span>
<span class="hljs-addition">+    for (let i=0;i&lt;list.length;i++){</span>
<span class="hljs-addition">+        let users=await User.find({room: list[i]._id});</span>
<span class="hljs-addition">+        console.log(users);</span>
<span class="hljs-addition">+        list[i].users=users;</span>
<span class="hljs-addition">+    }</span>
<span class="hljs-addition">+    console.log(list);</span>
</code></pre>
<h3 id="t497.4 routes/user.js">7.4 routes/user.js <a href="#t497.4 routes/user.js"> # </a></h3>
<p>server/routes/user.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+ router.post(&apos;/changeAvatar&apos;,async function (req,res) {</span>
<span class="hljs-addition">+     let {userId,avatar}=req.body;</span>
<span class="hljs-addition">+     try {</span>
<span class="hljs-addition">+         let user = await User.findById(userId);</span>
<span class="hljs-addition">+         user.avatar=avatar;</span>
<span class="hljs-addition">+         await user.save();</span>
<span class="hljs-addition">+         res.json({code:0,data:user});</span>
<span class="hljs-addition">+     } catch (error) {</span>
<span class="hljs-addition">+         res.json({code:1,error});</span>
<span class="hljs-addition">+     }</span>
<span class="hljs-addition">+ });</span>
</code></pre>
<h3 id="t507.5 Room/index.jsx">7.5 Room/index.jsx <a href="#t507.5 Room/index.jsx"> # </a></h3>
<p>src/pages/Room/index.jsx</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React,{Component} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;umi/link&apos;</span>;
<span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;dva&apos;</span>;
<span class="hljs-keyword">import</span> Cropper <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react-cropper&apos;</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">&apos;cropperjs/dist/cropper.css&apos;</span>; 
<span class="hljs-keyword">import</span> {Layout,Menu,Card,Input,Row,Col,Button,Form,List,Avatar,Modal} <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;antd&apos;</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./index.less&apos;</span>;
<span class="hljs-keyword">const</span> {Header,Footer,Content}=Layout;

@connect(<span class="hljs-function">(<span class="hljs-params">{room,login,loading}</span>) =&gt;</span> ({room,login}))
@Form.create()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rooms</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
    state={
        <span class="hljs-attr">src</span>: <span class="hljs-string">&apos;&apos;</span>,
        <span class="hljs-attr">cropperVisible</span>: <span class="hljs-literal">false</span>
    }
    createRoom=<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
        <span class="hljs-keyword">let</span> name=<span class="hljs-keyword">this</span>.props.form.getFieldValue(<span class="hljs-string">&apos;keyword&apos;</span>);
        <span class="hljs-keyword">if</span> (name) {
            <span class="hljs-keyword">this</span>.props.dispatch({
                <span class="hljs-attr">type</span>: <span class="hljs-string">&apos;room/create&apos;</span>,
                <span class="hljs-attr">payload</span>:{name}
            });
        }
    }
    <span class="hljs-comment">//&#x4E0A;&#x4F20;&#x56FE;&#x7247;</span>
    changeAvatar=<span class="hljs-function">(<span class="hljs-params">userId</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> that=<span class="hljs-keyword">this</span>;
        <span class="hljs-keyword">const</span> $input=<span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">&apos;input&apos;</span>);
        $input.style.display = <span class="hljs-string">&apos;none&apos;</span>;
        $input.setAttribute(<span class="hljs-string">&apos;type&apos;</span>, <span class="hljs-string">&apos;file&apos;</span>);
        $input.setAttribute(<span class="hljs-string">&apos;accept&apos;</span>,<span class="hljs-string">&apos;*/*&apos;</span>);
        $input.onchange=<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> file=e.target.files[<span class="hljs-number">0</span>];
            <span class="hljs-keyword">if</span> (!file) <span class="hljs-keyword">return</span>;
            <span class="hljs-keyword">const</span> reader=<span class="hljs-keyword">new</span> FileReader();
            reader.onloadend=<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                <span class="hljs-keyword">let</span> avatar=<span class="hljs-keyword">this</span>.result;
                that.setState({
                    <span class="hljs-attr">src</span>: avatar,
                    <span class="hljs-attr">cropperVisible</span>:<span class="hljs-literal">true</span>
                });

            }
            reader.readAsDataURL(file);
        }
        $input.click();
    }
    confirmChange=<span class="hljs-function">(<span class="hljs-params">userId</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> avatar = <span class="hljs-keyword">this</span>.cropper.getCroppedCanvas().toDataURL();
        <span class="hljs-keyword">this</span>.setState({<span class="hljs-attr">cropperVisible</span>:<span class="hljs-literal">false</span>});
        <span class="hljs-keyword">this</span>.props.dispatch({
               <span class="hljs-attr">type</span>: <span class="hljs-string">&apos;login/changeAvatar&apos;</span>,
               <span class="hljs-attr">payload</span>: {userId,avatar}
        }); 
    }
    render() {
        <span class="hljs-keyword">let</span> name=<span class="hljs-keyword">this</span>.props.form.getFieldValue(<span class="hljs-string">&apos;keyword&apos;</span>);
        <span class="hljs-keyword">let</span> rooms=<span class="hljs-keyword">this</span>.props.room.list;
        <span class="hljs-keyword">if</span> (name) {
            rooms = rooms.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.name.indexOf(name)!=<span class="hljs-number">-1</span>);
        }

        <span class="hljs-keyword">return</span> (
            &lt;Layout&gt;
                &lt;Header&gt;
                    &lt;Row&gt;
                        &lt;Col span={2}&gt;&lt;a className={styles.logo}&gt;&#x73E0;&#x5CF0;&#x804A;&#x5929;&#x5BA4;&lt;/a&gt;&lt;/Col&gt;
                        &lt;Col span={21}&gt;&lt;Menu
                        theme=&quot;dark&quot;
                        mode=&quot;horizontal&quot;
                        defaultSelectedKeys={[&apos;register&apos;]}
                        style={{ lineHeight: &apos;64px&apos; }}
                        &gt;
                        &lt;Menu.Item key=&quot;register&quot;&gt;&#x6CE8;&#x518C;&lt;/Menu.Item&gt;
                        &lt;Menu.Item key=&quot;login&quot;&gt;&#x767B;&#x5F55;&lt;/Menu.Item&gt;
                        &lt;/Menu&gt;&lt;/Col&gt;
                        &lt;Col span={1}&gt;{this.props.login.user&amp;&amp;&lt;Avatar onClick={()=&gt;this.changeAvatar(this.props.login.user._id)} src={this.props.login.user.avatar}/&gt;}&lt;/Col&gt;
                    &lt;/Row&gt;
                &lt;/Header&gt;
                &lt;Content&gt;
                    &lt;Card&gt;
                        &lt;Row gutter={16}&gt;
                            &lt;Col span={6} offset={8}&gt;
                                {
                                    this.props.form.getFieldDecorator(&apos;keyword&apos;)(
                                        &lt;Input type=&quot;text&quot; placeholder=&quot;&#x8BF7;&#x8F93;&#x5165;&#x623F;&#x95F4;&#x540D;&quot;&gt;&lt;/Input&gt;
                                    )
                                }
                            &lt;/Col&gt;
                        &lt;/Row&gt;                
                    &lt;/Card&gt;
                    &lt;Card&gt;
                        &lt;Row gutter={16}&gt;
                            {
                                rooms.length&gt;0?rooms.map(item =&gt; (
                                    &lt;Col span={6} key={item._id}&gt;
                                        &lt;Card
                                            title={item.name}
                                            extra={&lt;Link to={`/Room/${item._id}`}&gt;&#x8FDB;&#x5165;&lt;/Link&gt;}
                                        &gt;
                                            {
                                                item.users.map(user =&gt; &lt;Avatar style={{marginLeft:5}} src={user.avatar} /&gt;)
                                            }
                                        &lt;/Card&gt;
                                    &lt;/Col&gt;    
                                )):&lt;Button onClick={this.createRoom}&gt;&#x521B;&#x5EFA;&#x623F;&#x95F4;&lt;/Button&gt;
                            }
                        &lt;/Row&gt;
                    &lt;/Card&gt;
                &lt;/Content&gt;
                &lt;Footer&gt;
                    &lt;div className={styles.copyright}&gt; &#xA9;2018 &#x73E0;&#x5CF0;&#x57F9;&#x8BAD;&lt;/div&gt;
                &lt;/Footer&gt;
                &lt;Modal
                    onOk={()=&gt;this.confirmChange(this.props.login.user._id)}
                    onCancel={()=&gt;this.setState({cropperVisible:false})}
                    visible={this.state.cropperVisible} &gt;
                    &lt;Cropper
                            ref={i=&gt;this.cropper =i}
                            src={this.state.src}
                            style={{height: 400, width: 400}}
                            aspectRatio={16 / 9}
                        guides={false} /&gt;
                &lt;/Modal&gt;
            &lt;/Layout&gt;
        )
    }
}
</code></pre>
<h3 id="t517.6 /models/chat.js">7.6 /models/chat.js <a href="#t517.6 /models/chat.js"> # </a></h3>
<p>src/pages/Room/models/chat.js</p>
<pre><code class="lang-js">+ dispatch({<span class="hljs-attr">type</span>: <span class="hljs-string">&apos;login/save&apos;</span>,<span class="hljs-attr">payload</span>: {user}});
</code></pre>
<h3 id="t527.7 models/room.js">7.7 models/room.js <a href="#t527.7 models/room.js"> # </a></h3>
<p>src/pages/Room/models/room.js</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-        if(pathname == &apos;/Room&apos;){</span>
<span class="hljs-deletion">-          dispatch({type:&apos;getRooms&apos;});</span>
<span class="hljs-addition">+        if (pathname==&apos;/Room&apos;) {</span>
<span class="hljs-addition">+          let userStr = window.sessionStorage.getItem(&apos;user&apos;);</span>
<span class="hljs-addition">+          if (userStr) {</span>
<span class="hljs-addition">+            let user=JSON.parse(userStr);</span>
<span class="hljs-addition">+            dispatch({type: &apos;login/save&apos;,payload: {user}});</span>
<span class="hljs-addition">+            dispatch({type:&apos;getRooms&apos;});</span>
<span class="hljs-addition">+          } else {</span>
<span class="hljs-addition">+            router.push(&apos;/User/Login&apos;);</span>
<span class="hljs-addition">+          }</span>
</code></pre>
<h3 id="t537.8 models/login.js">7.8 models/login.js <a href="#t537.8 models/login.js"> # </a></h3>
<p>src/pages/User/models/login.js</p>
<pre><code class="lang-diff"><span class="hljs-addition">+    *changeAvatar({payload},{call,put}) {</span>
<span class="hljs-addition">+      let {code,data}=yield call(loginService.changeAvatar,payload);</span>
<span class="hljs-addition">+      if (code==0) {</span>
<span class="hljs-addition">+        window.sessionStorage.setItem(&apos;user&apos;,JSON.stringify(data));</span>
<span class="hljs-addition">+        yield put({type: &apos;save&apos;,payload: {user: data}});</span>
<span class="hljs-addition">+      }</span>
</code></pre>
<h3 id="t547.9 services/login.js">7.9 services/login.js <a href="#t547.9 services/login.js"> # </a></h3>
<p>src/pages/User/services/login.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeAvatar</span>(<span class="hljs-params">values</span>) </span>{
  <span class="hljs-keyword">return</span> request(<span class="hljs-string">`/user/changeAvatar`</span>,{
    <span class="hljs-attr">method</span>: <span class="hljs-string">&apos;POST&apos;</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(values),
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">&apos;Content-Type&apos;</span>: <span class="hljs-string">&quot;application/json&quot;</span>,
      <span class="hljs-string">&quot;Accept&quot;</span>:<span class="hljs-string">&quot;application/json&apos;&quot;</span>
    }
  });
}
</code></pre>
<h2 id="t55&#x53C2;&#x8003;&#x94FE;&#x63A5;">&#x53C2;&#x8003;&#x94FE;&#x63A5; <a href="#t55&#x53C2;&#x8003;&#x94FE;&#x63A5;"> # </a></h2>
<ul>
<li><a href="https://gitee.com/zhufengpeixun/zhufeng-dva-chat">zhufeng-dva-chat</a></li>
<li><a href="https://ant.design/docs/react/introduce-cn">ant.design</a></li>
<li><a href="https://pro.ant.design/index-cn">pro.ant.design</a></li>
<li><a href="https://umijs.org/zh/">umijs</a></li>
<li><a href="http://www.ucpaas.com">ucpaas</a></li>
</ul>

        <div class="copyright">Powered by <a href="https://github.com/jaywcjlove/idoc" target="_blank">idoc</a>. Dependence <a href="https://nodejs.org">Node.js</a> run.</div>
    </div>
    
</div>

<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.js"></script>
<script>
$('.warpper .page-toc ul ul li a').on('click',function(){
  $('.warpper .page-toc ul ul li a').removeClass('my-active')
  $(this).addClass('my-active')
})
  // if (!$('.understand-me').length) {
  //   var bar = $(window).height() - $('.navbar ').height() - $('.page-toc').position().top;
  //   var count = bar / 26 / 2;
  //   var barHeight = $('.page-toc').outerHeight();
  //   $('.page-toc li').eq(0).children('a').addClass('red');
  //   var arr = [];
  //   $("h1,h2,h3,h4,h5,h6").each(function () {
  //     arr.push($(this).position().top);
  //   });
  //   var timer
  //   function dark() {
  //     clearTimeout(timer)
  //      timer = setTimeout(function () {
  //      var top = Math.abs($('.page-toc > ul').position().top);
  //      var cur = $('.content').scrollTop();
  //      for (var i = arr.length; i >= 0; i--) {
  //        if (arr[i] <= cur) {
  //          break;
  //        }
  //      }
  //      if (i === -1) {
  //        i = 0;
  //      }
  //      $('.page-toc li a').removeClass('red');
  //      $('.page-toc li').eq(i).children('a').addClass('red');
  //      let height = $('.page-toc li').eq(i).position().top-$('.page-toc').height(); // 如果当前的offset出去了 回到中间可好？
  //      $('.page-toc').scrollTop(height+$('.page-toc').height()/2);
  //    },200)
  //   }

  //   $('.content').on('scroll', dark);
  // }
</script>
<style>

    /* ::-webkit-scrollbar{width:14px;}
    ::-webkit-scrollbar-track{background-color:transparent;}
    ::-webkit-scrollbar-thumb{background-color:transparent;}
    ::-webkit-scrollbar-thumb:hover {background-color:transparent}
    ::-webkit-scrollbar-thumb:active {background-color:transparent} */

    .page-toc > ul .red {
        background: #f3f3f3;
        z-index: 1;
        border-left: 3px solid #009a61;
        -webkit-transition: all .2s ease;
        transition: all .2s ease;
        color: #000
    }





</style>
</body>
</html>
